8000 Merge pull request #25169 from mtsokol/var-std-correction · numpy/numpy@8b0e7e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8b0e7e9

Browse files
authored
Merge pull request #25169 from mtsokol/var-std-correction
API: Introduce ``correction`` argument for ``np.var`` and ``np.std`` [Array API]
2 parents 5feea41 + 4540923 commit 8b0e7e9

File tree

8 files changed

+138
-35
lines changed

8 files changed

+138
-35
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
``correction`` argument for `numpy.var` and `numpy.std`
2+
-------------------------------------------------------
3+
4+
``correction`` argument was added to `numpy.var` and `numpy.std`,
5+
which is an Array API compatible alias for ``ddof``.
6+
As both arguments serve the same purpose only one of them can be
7+
provided at the same time.

doc/source/reference/array_api.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ functions to include additional keyword arguments from those required.
9999
- The definitions of ``rtol`` and ``rcond`` are the same, but their
100100
default values differ, making this **breaking**. See
101101
:ref:`array_api-linear-algebra-differences`.
102-
* - ``std`` and ``var``
103-
- ``correction``
104-
- ``ddof``
105-
-
106102
* - ``reshape``
107103
- ``shape``
108104
- ``newshape``

numpy/_core/fromnumeric.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3558,13 +3558,13 @@ def mean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, *,
35583558

35593559

35603560
def _std_dispatcher(a, axis=None, dtype=None, out=None, ddof=None,
3561-
keepdims=None, *, where=None, mean=None):
3561+
keepdims=None, *, where=None, mean=None, correction=None):
35623562
return (a, where, out, mean)
35633563

35643564

35653565
@array_function_dispatch(_std_dispatcher)
35663566
def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
3567-
where=np._NoValue, mean=np._NoValue):
3567+
where=np._NoValue, mean=np._NoValue, correction=np._NoValue):
35683568
r"""
35693569
Compute the standard deviation along the specified axis.
35703570
@@ -3592,7 +3592,7 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
35923592
Alternative output array in which to place the result. It must have
35933593
the same shape as the expected output but the type (of the calculated
35943594
values) will be cast if necessary.
3595-
ddof : int, optional
3595+
ddof : {int, float}, optional
35963596
Means Delta Degrees of Freedom. The divisor used in calculations
35973597
is ``N - ddof``, where ``N`` represents the number of elements.
35983598
By default `ddof` is zero. See Notes for details about use of `ddof`.
@@ -3612,14 +3612,20 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
36123612
36133613
.. versionadded:: 1.20.0
36143614
3615-
mean : array like, optional
3615+
mean : array_like, optional
36163616
Provide the mean to prevent its recalculation. The mean should have
36173617
a shape as if it was calculated with ``keepdims=True``.
36183618
The axis for the calculation of the mean should be the same as used in
36193619
the call to this std function.
36203620
36213621
.. versionadded:: 1.26.0
36223622
3623+
correction : {int, float}, optional
3624+
Array API compatible name for the ``ddof`` parameter. Only one of them
3625+
can be provided at the same time.
3626+
3627+
.. versionadded:: 2.0.0
3628+
36233629
Returns
36243630
-------
36253631
standard_deviation : ndarray, see dtype parameter above.
@@ -3736,6 +3742,14 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
37363742
if mean is not np._NoValue:
37373743
kwargs['mean'] = mean
37383744

3745+
if correction != np._NoValue:
3746+
if ddof != 0:
3747+
raise ValueError(
3748+
"ddof and correction can't be provided simultaneously."
3749+
)
3750+
else:
3751+
ddof = correction
3752+
37393753
if type(a) is not mu.ndarray:
37403754
try:
37413755
std = a.std
@@ -3749,13 +3763,13 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
37493763

37503764

37513765
def _var_dispatcher(a, axis=None, dtype=None, out=None, ddof=None,
3752-
keepdims=None, *, where=None, mean=None):
3766+
keepdims=None, *, where=None, mean=None, correction=None):
37533767
return (a, where, out, mean)
37543768

37553769

37563770
@array_function_dispatch(_var_dispatcher)
37573771
def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
3758-
where=np._NoValue, mean=np._NoValue):
3772+
where=np._NoValue, mean=np._NoValue, correction=np._NoValue):
37593773
r"""
37603774
Compute the variance along the specified axis.
37613775
@@ -3784,7 +3798,7 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
37843798
Alternate output array in which to place the result. It must have
37853799
the same shape as the expected output, but the type is cast if
37863800
necessary.
3787-
ddof : int, optional
3801+
ddof : {int, float}, optional
37883802
"Delta Degrees of Freedom": the divisor used in the calculation is
37893803
``N - ddof``, where ``N`` represents the number of elements. By
37903804
default `ddof` is zero. See notes for details about use of `ddof`.
@@ -3812,6 +3826,12 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
38123826
38133827
.. versionadded:: 1.26.0
38143828
3829+
correction : {int, float}, optional
3830+
Array API compatible name for the ``ddof`` parameter. Only one of them
3831+
can be provided at the same time.
3832+
3833+
.. versionadded:: 2.0.0
3834+
38153835
Returns
38163836
-------
38173837
variance : ndarray, see dtype parameter above
@@ -3927,6 +3947,14 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *,
39273947
if mean is not np._NoValue:
39283948
kwargs['mean'] = mean
39293949

3950+
if correction != np._NoValue:
3951+
if ddof != 0:
3952+
raise ValueError(
3953+
"ddof and correction can't be provided simultaneously."
3954+
)
3955+
else:
3956+
ddof = correction
3957+
39303958
if type(a) is not mu.ndarray:
39313959
try:
39323960
var = a.var

numpy/_core/fromnumeric.pyi

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -946,54 +946,64 @@ def std(
946946
axis: None = ...,
947947
dtype: None = ...,
948948
out: None = ...,
949-
ddof: float = ...,
949+
ddof: int | float = ...,
950950
keepdims: Literal[False] = ...,
951951
*,
952952
where: _ArrayLikeBool_co = ...,
953+
mean: _ArrayLikeComplex_co = ...,
954+
correction: int | float = ...,
953955
) -> floating[Any]: ...
954956
@overload
955957
def std(
956958
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
957959
axis: None | _ShapeLike = ...,
958960
dtype: None = ...,
959961
out: None = ...,
960-
ddof: float = ...,
962+
ddof: int | float = ...,
961963
keepdims: bool = ...,
962964
*,
963965
where: _ArrayLikeBool_co = ...,
966+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
967+
correction: int | float = ...,
964968
) -> Any: ...
965969
@overload
966970
def std(
967971
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
968972
axis: None = ...,
969973
dtype: _DTypeLike[_SCT] = ...,
970974
out: None = ...,
971-
ddof: float = ...,
975+
ddof: int | float = ...,
972976
keepdims: Literal[False] = ...,
973977
*,
974978
where: _ArrayLikeBool_co = ...,
979+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
980+
correction: int | float = ...,
975981
) -> _SCT: ...
976982
@overload
977983
def std(
978984
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
979985
axis: None | _ShapeLike = ...,
980986
dtype: DTypeLike = ...,
981987
out: None = ...,
982-
ddof: float = ...,
988+
ddof: int | float = ...,
983989
keepdims: bool = ...,
984990
*,
985991
where: _ArrayLikeBool_co = ...,
992+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
993+
correction: int | float = ...,
986994
) -> Any: ...
987995
@overload
988996
def std(
989997
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
990998
axis: None | _ShapeLike = ...,
991999
dtype: DTypeLike = ...,
9921000
out: _ArrayType = ...,
993-
ddof: float = ...,
1001+
ddof: int | float = ...,
9941002
keepdims: bool = ...,
9951003
*,
9961004
where: _ArrayLikeBool_co = ...,
1005+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
1006+
correction: int | float = ...,
9971007
) -> _ArrayType: ...
9981008

9991009
@overload
@@ -1002,54 +1012,64 @@ def var(
10021012
axis: None = ...,
10031013
dtype: None = ...,
10041014
out: None = ...,
1005-
ddof: float = ...,
1015+
ddof: int | float = ...,
10061016
keepdims: Literal[False] = ...,
10071017
*,
10081018
where: _ArrayLikeBool_co = ...,
1019+
mean: _ArrayLikeComplex_co = ...,
1020+
correction: int | float = ...,
10091021
) -> floating[Any]: ...
10101022
@overload
10111023
def var(
10121024
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
10131025
axis: None | _ShapeLike = ...,
10141026
dtype: None = ...,
10151027
out: None = ...,
1016-
ddof: float = ...,
1028+
ddof: int | float = ...,
10171029
keepdims: bool = ...,
10181030
*,
10191031
where: _ArrayLikeBool_co = ...,
1032+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
1033+
correction: int | float = ...,
10201034
) -> Any: ...
10211035
@overload
10221036
def var(
10231037
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
10241038
axis: None = ...,
10251039
dtype: _DTypeLike[_SCT] = ...,
10261040
out: None = ...,
1027-
ddof: float = ...,
1041+
ddof: int | float = ...,
10281042
keepdims: Literal[False] = ...,
10291043
*,
10301044
where: _ArrayLikeBool_co = ...,
1045+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
1046+
correction: int | float = ...,
10311047
) -> _SCT: ...
10321048
@overload
10331049
def var(
10341050
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
10351051
axis: None | _ShapeLike = ...,
10361052
dtype: DTypeLike = ...,
10371053
out: None = ...,
1038-
ddof: float = ...,
1054+
ddof: int | float = ...,
10391055
keepdims: bool = ...,
10401056
*,
10411057
where: _ArrayLikeBool_co = ...,
1058+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
1059+
correction: int | float = ...,
10421060
) -> Any: ...
10431061
@overload
10441062
def var(
10451063
a: _ArrayLikeComplex_co | _ArrayLikeObject_co,
10461064
axis: None | _ShapeLike = ...,
10471065
dtype: DTypeLike = ...,
10481066
out: _ArrayType = ...,
1049-
ddof: float = ...,
1067+
ddof: int | float = ...,
10501068
keepdims: bool = ...,
10511069
*,
10521070
where: _ArrayLikeBool_co = ...,
1071+
mean: _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
1072+
correction: int | float = ...,
10531073
) -> _ArrayType: ...
10541074

10551075
max = amax

numpy/_core/tests/test_numeric.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3085,6 +3085,22 @@ def test_ddof2(self):
30853085
assert_almost_equal(np.std(self.A, ddof=2)**2,
30863086
self.real_var * len(self.A) / (len(self.A) - 2))
30873087

3088+
def test_correction(self):
3089+
assert_almost_equal(
3090+
np.var(self.A, correction=1), np.var(self.A, ddof=1)
3091+
)
3092+
assert_almost_equal(
3093+
np.std(self.A, correction=1), np.std(self.A, ddof=1)
3094+
)
3095+
3096+
err_msg = "ddof and correction can't be provided simultaneously."
3097+
3098+
with assert_raises_regex(ValueError, err_msg):
3099+
np.var(self.A, ddof=1, correction=0)
3100+
3101+
with assert_raises_regex(ValueError, err_msg):
3102+
np.std(self.A, ddof=1, correction=1)
3103+
30883104
def test_out_scalar(self):
30893105
d = np.arange(10)
30903106
out = np.array(0.)

0 commit comments

Comments
 (0)
0