Skip to content

Adding np.nanmean(), nanstd(), and nanvar(), gh-3297 branched. #3416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion doc/source/reference/routines.statistics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ Averages and variances
.. autosummary::
:toctree: generated/

median
average
mean
median
std
var
nanmean
nanstd
nanvar

Correlating
-----------
Expand Down
19 changes: 12 additions & 7 deletions numpy/core/_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from numpy.core import multiarray as mu
from numpy.core import umath as um
from numpy.core.numeric import asanyarray
from numpy.core import numerictypes as nt

def _amax(a, axis=None, out=None, keepdims=False):
return um.maximum.reduce(a, axis=axis,
Expand Down Expand Up @@ -46,42 +47,45 @@ def _count_reduce_items(arr, axis):
def _mean(a, axis=None, dtype=None, out=None, keepdims=False):
arr = asanyarray(a)

# Upgrade bool, unsigned int, and int to float64
if dtype is None and arr.dtype.kind in ['b','u','i']:
# Cast bool, unsigned int, and int to float64
if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
ret = um.add.reduce(arr, axis=axis, dtype='f8',
out=out, keepdims=keepdims)
else:
ret = um.add.reduce(arr, axis=axis, dtype=dtype,
out=out, keepdims=keepdims)

rcount = _count_reduce_items(arr, axis)
if isinstance(ret, mu.ndarray):
ret = um.true_divide(ret, rcount,
out=ret, casting='unsafe', subok=False)
else:
ret = ret / float(rcount)
ret = ret / rcount

return ret

def _var(a, axis=None, dtype=None, out=None, ddof=0,
keepdims=False):
arr = asanyarray(a)

# First compute the mean, saving 'rcount' for reuse later
if dtype is None and arr.dtype.kind in ['b','u','i']:
if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
arrmean = um.add.reduce(arr, axis=axis, dtype='f8', keepdims=True)
else:
arrmean = um.add.reduce(arr, axis=axis, dtype=dtype, keepdims=True)

rcount = _count_reduce_items(arr, axis)
if isinstance(arrmean, mu.ndarray):
arrmean = um.true_divide(arrmean, rcount,
out=arrmean, casting='unsafe', subok=False)
else:
arrmean = arrmean / float(rcount)
arrmean = arrmean / rcount

# arr - arrmean
x = arr - arrmean

# (arr - arrmean) ** 2
if arr.dtype.kind == 'c':
if issubclass(arr.dtype.type, nt.complex_):
x = um.multiply(x, um.conjugate(x), out=x).real
else:
x = um.multiply(x, x, out=x)
Expand All @@ -97,7 +101,7 @@ def _var(a, axis=None, dtype=None, out=None, ddof=0,
ret = um.true_divide(ret, rcount,
out=ret, casting='unsafe', subok=False)
else:
ret = ret / float(rcount)
ret = ret / rcount

return ret

Expand All @@ -111,3 +115,4 @@ def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
ret = um.sqrt(ret)

return ret

28 changes: 13 additions & 15 deletions numpy/core/fromnumeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@


# functions that are now methods
__all__ = ['take', 'reshape', 'choose', 'repeat', 'put',
'swapaxes', 'transpose', 'sort', 'argsort', 'argmax', 'argmin',
'searchsorted', 'alen',
'resize', 'diagonal', 'trace', 'ravel', 'nonzero', 'shape',
'compress', 'clip', 'sum', 'product', 'prod', 'sometrue', 'alltrue',
'any', 'all', 'cumsum', 'cumproduct', 'cumprod', 'ptp', 'ndim',
'rank', 'size', 'around', 'round_', 'mean', 'std', 'var', 'squeeze',
'amax', 'amin',
]
__all__ = [
'take', 'reshape', 'choose', 'repeat', 'put', 'swapaxes', 'transpose',
'sort', 'argsort', 'argmax', 'argmin', 'searchsorted', 'alen',
'resize', 'diagonal', 'trace', 'ravel', 'nonzero', 'shape', 'compress',
'clip', 'sum', 'product', 'prod', 'sometrue', 'alltrue', 'any', 'all',
'cumsum', 'cumproduct', 'cumprod', 'ptp', 'ndim', 'rank', 'size',
'around', 'round_', 'mean', 'std', 'var', 'squeeze', 'amax', 'amin', ]


try:
Expand Down Expand Up @@ -62,9 +60,9 @@ def take(a, indices, axis=None, out=None, mode='raise'):
The source array.
indices : array_like
The indices of the values to extract.

.. versionadded:: 1.8.0

Also allow scalars for indices.
axis : int, optional
The axis over which to select values. By default, the flattened
Expand Down Expand Up @@ -2517,6 +2515,7 @@ def mean(a, axis=None, dtype=None, out=None, keepdims=False):
See Also
--------
average : Weighted average
std, var, nanmean, nanstd, nanvar

Notes
-----
Expand Down Expand Up @@ -2563,7 +2562,6 @@ def mean(a, axis=None, dtype=None, out=None, keepdims=False):
return _methods._mean(a, axis=axis, dtype=dtype,
out=out, keepdims=keepdims)


def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
"""
Compute the standard deviation along the specified axis.
Expand Down Expand Up @@ -2604,7 +2602,7 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):

See Also
--------
var, mean
var, mean, nanmean, nanstd, nanvar
numpy.doc.ufuncs : Section "Output arguments"

Notes
Expand Down Expand Up @@ -2707,8 +2705,7 @@ def var(a, axis=None, dtype=None, out=None, ddof=0,

See Also
--------
std : Standard deviation
mean : Average
std , mean, nanmean, nanstd, nanvar
numpy.doc.ufuncs : Section "Output arguments"

Notes
Expand Down Expand Up @@ -2767,3 +2764,4 @@ def var(a, axis=None, dtype=None, out=None, ddof=0,

return _methods._var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
keepdims=keepdims)

18 changes: 16 additions & 2 deletions numpy/core/tests/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import platform
from decimal import Decimal
import warnings

import numpy as np
from numpy.core import *
Expand Down Expand Up @@ -177,18 +178,33 @@ def test_mean(self):
assert_(all(mean(A,0) == array([2.5,3.5,4.5])))
assert_(all(mean(A,1) == array([2.,5.])))

with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', RuntimeWarning)
assert_(isnan(mean([])))
assert_(w[0].category is RuntimeWarning)

def test_std(self):
A = [[1,2,3],[4,5,6]]
assert_almost_equal(std(A), 1.707825127659933)
assert_almost_equal(std(A,0), array([1.5, 1.5, 1.5]))
assert_almost_equal(std(A,1), array([0.81649658, 0.81649658]))

with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', RuntimeWarning)
assert_(isnan(std([])))
assert_(w[0].category is RuntimeWarning)

def test_var(self):
A = [[1,2,3],[4,5,6]]
assert_almost_equal(var(A), 2.9166666666666665)
assert_almost_equal(var(A,0), array([2.25, 2.25, 2.25]))
assert_almost_equal(var(A,1), array([0.66666667, 0.66666667]))

with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', RuntimeWarning)
assert_(isnan(mean([])))
assert_(w[0].category is RuntimeWarning)


class TestBoolScalar(TestCase):
def test_logical(self):
Expand Down Expand Up @@ -1367,7 +1383,6 @@ def test_no_parameter_modification(self):
assert_array_equal(x, array([inf, 1]))
assert_array_equal(y, array([0, inf]))


class TestStdVar(TestCase):
def setUp(self):
self.A = array([1,-1,1,-1])
Expand All @@ -1389,7 +1404,6 @@ def test_ddof2(self):
assert_almost_equal(std(self.A,ddof=2)**2,
self.real_var*len(self.A)/float(len(self.A)-2))


class TestStdVarComplex(TestCase):
def test_basic(self):
A = array([1,1.j,-1,-1.j])
Expand Down
5 changes: 4 additions & 1 deletion numpy/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from __future__ import division, absolute_import, print_function

import math

from .info import __doc__
from numpy.version import version as __version__

from .type_check import *
from .index_tricks import *
from .function_base import *
from .nanfunctions import *
from .shape_base import *
from .stride_tricks import *
from .twodim_base import *
Expand All @@ -18,7 +21,6 @@
from .arraysetops import *
from .npyio import *
from .financial import *
import math
from .arrayterator import *
from .arraypad import *

Expand All @@ -36,6 +38,7 @@
__all__ += arraysetops.__all__
__all__ += npyio.__all__
__all__ += financial.__all__
__all__ += nanfunctions.__all__

from numpy.testing import Tester
test = Tester().test
Expand Down
Loading