Skip to content

Commit 18d0015

Browse files
authored
Merge pull request #1646 from scipy:1.18/stats/lmoment-distribution-method
👽️ `stats.ContinuousDistribution.lmoment`: new method
2 parents 1e04acb + 81e3b04 commit 18d0015

3 files changed

Lines changed: 39 additions & 29 deletions

File tree

.mypyignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ scipy\.stats\.(_new_distributions\.)?Normal\.__new__
2121
# TODO: 1.18.0rc1
2222

2323
scipy.stats._bws_test.bws_test
24-
scipy.stats._distribution_infrastructure.Mixture.lmoment
25-
scipy.stats._distribution_infrastructure.OrderStatisticDistribution._n_domain
26-
scipy.stats._distribution_infrastructure.OrderStatisticDistribution._r_domain
27-
scipy.stats._distribution_infrastructure.UnivariateDistribution.lmoment
28-
scipy.stats._probability_distribution._ProbabilityDistribution.lmoment
2924

3025
scipy.stats._morestats.ansari
3126
scipy.stats._morestats.boxcox

scipy-stubs/stats/_distribution_infrastructure.pyi

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import optype.numpy as onp
2929
import optype.numpy.compat as npc
3030

3131
from ._distn_infrastructure import rv_continuous
32-
from ._probability_distribution import _ProbabilityDistribution
32+
from ._probability_distribution import _LMomentMethod, _ProbabilityDistribution
3333
from ._qmc import QMCEngine
3434

3535
__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"]
@@ -61,15 +61,15 @@ _DistT_co = TypeVar("_DistT_co", bound=_Dist[tuple[int, ...]], default=Univariat
6161

6262
_AxesT = TypeVar("_AxesT", bound=_Axes, default=Any)
6363

64-
_ParameterEndpoint: TypeAlias = onp.ToFloat | Callable[..., onp.ToFloat] | str
65-
_ParameterTuple: TypeAlias = tuple[_ParameterEndpoint, _ParameterEndpoint]
64+
type _ParameterEndpoint = onp.ToFloat | Callable[..., onp.ToFloat] | str
65+
type _ParameterTuple = tuple[_ParameterEndpoint, _ParameterEndpoint]
6666

6767
# NOTE: `TypedDict` with `NotRequired` cannot be used, because `NotRequired` does not
6868
# mean "not required": Other `TypedDict` MUST also include them to be assignable,
6969
# so a `NotRequired` value is REQUIRED. Absolutely ridiculous...
7070
# https://typing.python.org/en/latest/spec/typeddict.html#id4
71-
_ParameterDict: TypeAlias = Mapping[str, tuple[Any, ...]]
72-
_ParameterSpec: TypeAlias = _ParameterDict | _ParameterTuple
71+
type _ParameterDict = Mapping[str, tuple[Any, ...]]
72+
type _ParameterSpec = _ParameterDict | _ParameterTuple
7373

7474
@type_check_only
7575
class _DuckDistributionBase(Protocol[_Tss]):
@@ -494,6 +494,10 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape
494494
method: _SMomentMethod | None = None,
495495
) -> _FloatND[_ShapeT1]: ...
496496

497+
#
498+
@override
499+
def lmoment(self, /, order: int = 1, *, standardize: bool = True, method: _LMomentMethod | None = None) -> np.float64: ... # pyright: ignore[reportIncompatibleMethodOverride] # pyrefly:ignore[bad-override] # ty:ignore[invalid-method-override]
500+
497501
#
498502
@override
499503
@overload
@@ -1235,6 +1239,8 @@ class UnivariateDistribution(_BaseDistribution[_XT_co], Generic[_XT_co, _ShapeT0
12351239
t: tuple[_PlotQuantity, onp.ToJustFloat, onp.ToJustFloat] | None = None,
12361240
ax: _AxesT | None = None,
12371241
) -> _AxesT: ...
1242+
1243+
#
12381244
def __neg__(self, /) -> _LinDist[Self, _FloatT_co, _ShapeT_co]: ...
12391245
def __abs__(self, /) -> _FoldDist[Self, _FloatT_co, _ShapeT_co]: ...
12401246

@@ -1425,10 +1431,10 @@ class TruncatedDistribution(_TransDist[_DistT_co, _Float, _ShapeT_co], Generic[_
14251431

14261432
# always float64 or longdouble
14271433
class OrderStatisticDistribution(_TransDist[_DistT_co, _OutFloat, _ShapeT_co], Generic[_DistT_co, _ShapeT_co]):
1428-
# these should actually be integral; but the `_IntegerDomain` isn't finished yet
1429-
_r_domain: ClassVar[_RealInterval] = ...
1434+
_r_domain: ClassVar[_IntegerInterval] = ...
14301435
_r_param: ClassVar[_RealParameter] = ...
1431-
_n_domain: ClassVar[_RealInterval] = ...
1436+
1437+
_n_domain: ClassVar[_IntegerInterval] = ...
14321438
_n_param: ClassVar[_RealParameter] = ...
14331439

14341440
@overload
@@ -1524,6 +1530,10 @@ class Mixture(_BaseDistribution[_FloatT_co, _0D], Generic[_FloatT_co]):
15241530
@override
15251531
def kurtosis(self, /, *, method: _SMomentMethod | None = None) -> _OutFloat: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override]
15261532

1533+
# always raises NotImplementedError`
1534+
@override
1535+
def lmoment(self, order: int = 1, *, standardize: bool = False, method: _LMomentMethod | None = None) -> Never: ...
1536+
15271537
###
15281538

15291539
# still waiting on the intersection type PEP...

scipy-stubs/stats/_probability_distribution.pyi

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import abc
22
import types
3-
from typing import Any, Generic, Literal as L, TypeAlias, overload
3+
from typing import Any, Generic, Literal as L, overload
44
from typing_extensions import TypeVar
55

66
import numpy as np
@@ -11,22 +11,23 @@ from ._qmc import QMCEngine
1111

1212
_XT_co = TypeVar("_XT_co", bound=npc.number, default=np.float64, covariant=True)
1313

14-
_MedianMethod: TypeAlias = L["formula", "icdf"] | None
15-
_ModeMethod: TypeAlias = L["formula", "optimization"] | None
16-
_SampleMethod: TypeAlias = L["formula", "inverse_transform"] | None
17-
_RMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache"] | None
18-
_CMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache", "normalize"] | None
19-
_SMomentMethod: TypeAlias = L["formula", "transform", "general", "cache", "normalize"] | None
20-
_EntropyMethod: TypeAlias = L["formula", "logexp", "quadrature"] | None
21-
_PXFMethod: TypeAlias = L["formula", "logexp"] | None
22-
_CDFMethod: TypeAlias = L["formula", "logexp", "complement", "quadrature", "subtraction"] | None
23-
_CCDFMethod: TypeAlias = L["formula", "logexp", "complement", "quadrature", "addition"] | None
24-
_ICDFMethod: TypeAlias = L["formula", "complement", "inversion"] | None
14+
type _MedianMethod = L["formula", "icdf"] | None
15+
type _ModeMethod = L["formula", "optimization"] | None
16+
type _SampleMethod = L["formula", "inverse_transform"] | None
17+
type _RMomentMethod = L["formula", "transform", "quadrature", "cache"] | None
18+
type _CMomentMethod = L["formula", "transform", "quadrature", "cache", "normalize"] | None
19+
type _SMomentMethod = L["formula", "transform", "general", "cache", "normalize"] | None
20+
type _LMomentMethod = L["formula", "general", "order_statistics", "quadrature_icdf", "cache"]
21+
type _EntropyMethod = L["formula", "logexp", "quadrature"] | None
22+
type _PXFMethod = L["formula", "logexp"] | None
23+
type _CDFMethod = L["formula", "logexp", "complement", "quadrature", "subtraction"] | None
24+
type _CCDFMethod = L["formula", "logexp", "complement", "quadrature", "addition"] | None
25+
type _ICDFMethod = L["formula", "complement", "inversion"] | None
2526

26-
_Float: TypeAlias = np.float64 | np.longdouble
27-
_Complex: TypeAlias = np.complex128 | np.clongdouble
28-
_FloatND: TypeAlias = onp.ArrayND[_Float]
29-
_ToFloat0ND: TypeAlias = onp.ToFloat | onp.ToFloatND
27+
type _Float = np.float64 | np.longdouble
28+
type _Complex = np.complex128 | np.clongdouble
29+
type _FloatND = onp.ArrayND[_Float]
30+
type _ToFloat0ND = onp.ToFloat | onp.ToFloatND
3031

3132
###
3233

@@ -69,6 +70,10 @@ class _ProbabilityDistribution(Generic[_XT_co], metaclass=abc.ABCMeta):
6970
@abc.abstractmethod
7071
def moment(self, /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod) -> _Float | _FloatND: ...
7172

73+
# The `kind` param here is wrong: https://github.com/scipy/scipy/pull/25243
74+
@abc.abstractmethod
75+
def lmoment(self, /, order: int, kind: bool, *, method: _LMomentMethod | None) -> _Float | _FloatND: ...
76+
7277
#
7378
@abc.abstractmethod
7479
def entropy(self, /, *, method: _EntropyMethod) -> _Float | _FloatND: ...

0 commit comments

Comments
 (0)