Skip to Content

VONMISES_FISHER

Overview

The VONMISES_FISHER function computes the probability density function (PDF), log-PDF, entropy, or draws random samples from the von Mises-Fisher distribution on the unit hypersphere. This distribution is widely used in directional statistics for modeling data distributed on the surface of a sphere or hypersphere, such as orientations, directions, or unit vectors in 3D or higher dimensions. The PDF is given by:

f(x;μ,κ)=Cd(κ)exp(κμTx)f(x; \mu, \kappa) = C_d(\kappa) \exp(\kappa \mu^T x)

where xx is a unit vector, μ\mu is the mean direction (unit vector), κ\kappa is the concentration parameter (κ>0\kappa > 0), and Cd(κ)C_d(\kappa) is a normalization constant depending on the dimension dd and κ\kappa. For more details, see the scipy.stats.vonmises_fisher documentation.

This wrapper exposes only the most commonly used parameters: mean direction (mu), concentration (kappa), evaluation points (x), method, and sample size. Parameters for random state and fitting are not supported. This example function is provided as-is without any representation of accuracy.

Usage

To use the function in Excel:

=VONMISES_FISHER(x, mu, kappa, [method], [size])
  • x (2D list, required for ‘pdf’ and ‘logpdf’): Table of points (each row is a unit vector) at which to evaluate the function. Each row must have the same dimension as mu.
  • mu (2D column vector, required): Mean direction of the distribution. Must be a unit vector (norm = 1), shape is {d,1}.
  • kappa (float, required): Concentration parameter. Must be positive.
  • method (string, optional, default=pdf): Which method to compute: pdf, logpdf, entropy, or rvs.
  • size (integer, optional, only for rvs): Number of samples to draw if method is rvs.

The function returns a 2D list of results for each input point (for pdf and logpdf), a single value for entropy, or a 2D list of samples for rvs. If the input is invalid, an error message (string) is returned.

Examples

Example 1: PDF at a Point

Inputs:

xmukappamethod
1.00.00.01.00.00.02.0pdf

Excel formula:

=VONMISES_FISHER({1,0,0}, {1;0;0}, 2, "pdf")

Expected output:

Result
0.324

Example 2: Log-PDF at a Point

Inputs:

xmukappamethod
1.00.00.01.00.00.02.0logpdf

Excel formula:

=VONMISES_FISHER({1,0,0}, {1;0;0}, 2, "logpdf")

Expected output:

Result
-1.126

Example 3: Entropy of the Distribution

Inputs:

mukappamethod
1.00.00.02.0entropy

Excel formula:

=VONMISES_FISHER(, {1;0;0}, 2, "entropy")

Expected output:

Result
2.052

Example 4: Draw a Random Sample

Inputs:

mukappamethodsize
1.00.00.02.0rvs1

Excel formula:

=VONMISES_FISHER(, {1;0;0}, 2, "rvs", 1)

Expected output:

Result (sample)
(varies)

The output for rvs is a random unit vector sampled from the distribution; values will vary each time the function is called.

Python Code

from scipy.stats import vonmises_fisher as scipy_vonmises_fisher from typing import List, Optional, Union def vonmises_fisher(x: Optional[List[List[float]]] = None, mu: Optional[List[List[float]]] = None, kappa: Optional[float] = None, method: str = 'pdf', size: Optional[int] = None) -> Union[List[List[Optional[float]]], str]: """ Computes the PDF, log-PDF, entropy, or draws random samples from a von Mises-Fisher distribution on the unit hypersphere. Args: x: 2D list of float values. Points at which to evaluate the function (required for 'pdf' and 'logpdf'). mu: 2D list of float values (column vector). Mean direction of the distribution. Must be a unit vector. Required. kappa: Concentration parameter (float). Must be positive. Required. method: Which method to compute (str): 'pdf', 'logpdf', 'entropy', 'rvs'. Default is 'pdf'. size: Number of samples to draw if method is 'rvs'. Optional. Returns: 2D list of results for each input point, or an error message (str) if input is invalid. This example function is provided as-is without any representation of accuracy. """ # Validate method valid_methods = {'pdf', 'logpdf', 'entropy', 'rvs'} if method not in valid_methods: return f"Invalid method: {method}. Must be one of {valid_methods}." # Validate mu if mu is None or not isinstance(mu, list) or not all(isinstance(row, list) and len(row) == 1 for row in mu): return "Invalid input: mu must be a 2D list (column vector) with shape (d, 1)." try: mu_vec = [float(row[0]) for row in mu] except Exception: return "Invalid input: mu must contain numeric values." # Check if mu is a unit vector import math norm_mu = math.sqrt(sum(x**2 for x in mu_vec)) if not math.isclose(norm_mu, 1.0, rel_tol=1e-5): return "Invalid input: mu must be a unit vector (norm = 1)." # Validate kappa if kappa is None: return "Invalid input: kappa (concentration) must be specified." try: kappa_val = float(kappa) except Exception: return "Invalid input: kappa must be a float." if kappa_val <= 0: return "Invalid input: kappa must be positive." dist = scipy_vonmises_fisher(mu=mu_vec, kappa=kappa_val) import numpy as np def to_native_float(val): if isinstance(val, (float, int)): return float(val) if hasattr(val, 'item'): return float(val.item()) return val if method == 'entropy': try: ent = dist.entropy() except Exception as e: return f"scipy_vonmises_fisher entropy error: {e}" return [[to_native_float(ent)]] if method == 'rvs': if size is None: size_val = 1 else: try: size_val = int(size) except Exception: return "Invalid input: size must be an integer." if size_val <= 0: return "Invalid input: size must be positive." try: samples = dist.rvs(size=size_val) except Exception as e: return f"scipy_vonmises_fisher rvs error: {e}" arr = np.array(samples) if arr.ndim == 1: return [[to_native_float(x) for x in arr.tolist()]] elif arr.ndim == 2: return [[to_native_float(x) for x in row] for row in arr.tolist()] else: return "Invalid output shape from rvs." # For pdf/logpdf, x is required if x is None or not isinstance(x, list) or not all(isinstance(row, list) for row in x): return "Invalid input: x must be a 2D list of points." # Check each row in x matches mu dimension if any(len(row) != len(mu_vec) for row in x): return "Invalid input: each row in x must have the same dimension as mu." results = [] for row in x: try: point = [float(val) for val in row] except Exception: results.append([None]) continue try: if method == 'pdf': val = dist.pdf(point) else: val = dist.logpdf(point) # Disallow nan/inf val_native = to_native_float(val) if isinstance(val_native, float) and (math.isnan(val_native) or math.isinf(val_native)): results.append([None]) else: results.append([val_native]) except Exception: results.append([None]) return results

Example Workbook

Link to Workbook

Last updated on