Source code for comyx.stats.common

from __future__ import annotations

from typing import Any, Tuple

import numpy as np
import numpy.typing as npt
import scipy.stats as stats

from .moments import approx_gamma_params

NDArrayFloat = npt.NDArray[np.floating[Any]]
RVDistribution = Any


[docs] def gamma_add_params( mu_a_1: NDArrayFloat, mu_a_2: NDArrayFloat, mu_b_1: NDArrayFloat, mu_b_2: NDArrayFloat, a: NDArrayFloat = np.array([1.0]), b: NDArrayFloat = np.array([1.0]), return_type: str = "params", ) -> Tuple[NDArrayFloat, NDArrayFloat]: r"""Computes the parameters of the sum of two independent Gamma random variables. The first distribution is optionally weighted by a, and the second by b. .. math:: z = a h + b g , where :math:`h \sim \Gamma(k_a, \theta_a)` and :math:`g \sim \Gamma(k_b, \theta_b)`. Also, .. math:: k_n = \frac{\mu_{n,1}^{(2)}}{\mu_{n,2} - \mu_{n,1}^{(2)}} .. math:: \theta_n = \frac{\mu_{n,2} - \mu_{n,1}^{(2)}}{\mu_{n,1}} , where :math:`n \in \{a, b\}`. The resulting distribution is a Gamma distribution, expressed as: .. math:: z \sim \Gamma(k_z, \theta_z) Args: mu_a_1: First moment of the first Gamma distribution :math:`h`. mu_a_2: Second moment of the first Gamma distribution :math:`h`. mu_b_1: First moment of the second Gamma distribution :math:`g`. mu_b_2: Second moment of the second Gamma distribution :math:`g`. a: Shape parameter of the first Gamma distribution :math:`h`. b: Shape parameter of the second Gamma distribution :math:`g`. return_type: Return type of the function. Must be either "params" or "moments". Returns: Desired parameters of the sum of a Gamma random variable and one. If return_type is "params", returns the shape and scale parameters of the sum of two independent Gamma random variables. If return_type is "moments", returns the first two moments of the sum of two independent Gamma random variables. """ mu_1 = (mu_a_1 * a) + (mu_b_1 * b) mu_2 = (a**2 * mu_a_2) + (b**2 * mu_b_2) + (2 * a * b * mu_a_1 * mu_b_1) if return_type == "params": return approx_gamma_params(mu_1, mu_2) elif return_type == "moments": return mu_1, mu_2 else: raise ValueError("return_type must be either 'params' or 'moments'")
[docs] def gamma_plus_one_params( mu_a_1: NDArrayFloat, mu_a_2: NDArrayFloat, a: NDArrayFloat = np.array([1.0]), return_type: str = "params", ) -> Tuple[NDArrayFloat, NDArrayFloat]: r"""Computes the parameters of the sum of a Gamma random variable and one. .. math:: z = h + 1 , where :math:`h \sim \Gamma(k_a, \theta_a)`. Also, .. math:: k_a = \frac{\mu_{a,1}^{(2)}}{\mu_{a,2} - \mu_{a,1}^{(2)}} .. math:: \theta_a = \frac{\mu_{a,2} - \mu_{a,1}^{(2)}}{\mu_{a,1}} Args: mu_a_1: First moment of the Gamma distribution. mu_a_2: Second moment of the Gamma distribution. return_type: Return type of the function. Must be either "params" or "moments". Returns: Desired parameters of the sum of a Gamma random variable and one. If return_type is "params", returns the shape and scale parameters of the sum of a Gamma random variable and one. If return_type is "moments", returns the first two moments of the sum of a Gamma random variable and one. """ mu_1 = (a * mu_a_1) + 1 mu_2 = (a**2 * mu_a_2) + (2 * a * mu_a_1) + 1 if return_type == "params": return approx_gamma_params(mu_1, mu_2) elif return_type == "moments": return mu_1, mu_2 else: raise ValueError("return_type must be either 'params' or 'moments'")
[docs] def gamma_div_gamma_dist( k_a: NDArrayFloat, k_b: NDArrayFloat, theta_a: NDArrayFloat, theta_b: NDArrayFloat ) -> RVDistribution: r"""Computes the parameters of the ratio of two independent Gamma random variables. .. math:: z = \frac{h}{g} , where :math:`h \sim \Gamma(k_a, \theta_a)` and :math:`g \sim \Gamma(k_b, \theta_b)`. The resulting distribution is a Beta prime distribution, expressed as: .. math:: z \sim \beta'(k_a, k_b, \theta_a / \theta_b) Args: k_a: Shape parameter of the first Gamma distribution :math:`h`. k_b: Shape parameter of the second Gamma distribution :math:`g`. theta_a: Scale parameter of the first Gamma distribution :math:`h`. theta_b: Scale parameter of the second Gamma distribution :math:`g`. Returns: A beta prime distribution with shape parameters k_a and k_b, and scale parameter theta_a / theta_b. """ dist = stats.betaprime(k_a, k_b, loc=0, scale=theta_a / theta_b) return dist
__all__ = [ "gamma_add_params", "gamma_plus_one_params", "gamma_div_gamma_dist", ]