diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2013-06-15 09:56:29 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2013-06-15 09:56:29 -0700 |
commit | e036deb49b74fc2432066497d7c1d4bb61a74caa (patch) | |
tree | f52f964db3769b1f482388653873021dfe6de3bf | |
parent | fa5bc1c0e6f96f50dc4f20195ab6b1180726cb23 (diff) | |
parent | ace8ee7b4b81af7600c53e093e104ef53d54482c (diff) | |
download | numpy-e036deb49b74fc2432066497d7c1d4bb61a74caa.tar.gz |
Merge pull request #3440 from WarrenWeckesser/bug-ma-average
BUG: ma: ma.average didn't handle complex arrays correctly (issue gh-2684)
-rw-r--r-- | numpy/ma/extras.py | 14 | ||||
-rw-r--r-- | numpy/ma/tests/test_extras.py | 171 |
2 files changed, 117 insertions, 68 deletions
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index 5a484ce9d..d14812093 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -455,7 +455,8 @@ def average(a, axis=None, weights=None, returned=False): The weights array can either be 1-D (in which case its length must be the size of `a` along the given axis) or of the same shape as `a`. If ``weights=None``, then all data in `a` are assumed to have a - weight equal to one. + weight equal to one. If `weights` is complex, the imaginary parts + are ignored. returned : bool, optional Flag indicating whether a tuple ``(result, sum of weights)`` should be returned as output (True), or just the result (False). @@ -515,7 +516,7 @@ def average(a, axis=None, weights=None, returned=False): if mask is nomask: if weights is None: d = ash[axis] * 1.0 - n = add.reduce(a._data, axis, dtype=float) + n = add.reduce(a._data, axis) else: w = filled(weights, 0.0) wsh = w.shape @@ -531,14 +532,14 @@ def average(a, axis=None, weights=None, returned=False): r = [None] * len(ash) r[axis] = slice(None, None, 1) w = eval ("w[" + repr(tuple(r)) + "] * ones(ash, float)") - n = add.reduce(a * w, axis, dtype=float) + n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) del w, r else: raise ValueError('average: weights wrong shape.') else: if weights is None: - n = add.reduce(a, axis, dtype=float) + n = add.reduce(a, axis) d = umath.add.reduce((-mask), axis=axis, dtype=float) else: w = filled(weights, 0.0) @@ -547,7 +548,7 @@ def average(a, axis=None, weights=None, returned=False): wsh = (1,) if wsh == ash: w = array(w, dtype=float, mask=mask, copy=0) - n = add.reduce(a * w, axis, dtype=float) + n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) elif wsh == (ash[axis],): ni = ash[axis] @@ -555,7 +556,7 @@ def average(a, axis=None, weights=None, returned=False): r[axis] = slice(None, None, 1) w = eval ("w[" + repr(tuple(r)) + \ "] * masked_array(ones(ash, float), mask)") - n = add.reduce(a * w, axis, dtype=float) + n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) else: raise ValueError('average: weights wrong shape.') @@ -580,7 +581,6 @@ def average(a, axis=None, weights=None, returned=False): return result - def median(a, axis=None, out=None, overwrite_input=False): """ Compute the median along the specified axis. diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py index d9f94a01f..4b30813b2 100644 --- a/numpy/ma/tests/test_extras.py +++ b/numpy/ma/tests/test_extras.py @@ -16,9 +16,18 @@ __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' import numpy as np from numpy.testing import TestCase, run_module_suite -from numpy.ma.testutils import * -from numpy.ma.core import * -from numpy.ma.extras import * +from numpy.ma.testutils import (rand, assert_, assert_array_equal, + assert_equal, assert_almost_equal) +from numpy.ma.core import (array, arange, masked, MaskedArray, masked_array, + getmaskarray, shape, nomask, ones, zeros, count) +from numpy.ma.extras import (atleast_2d, mr_, dot, polyfit, + cov, corrcoef, median, average, + unique, setxor1d, setdiff1d, union1d, intersect1d, in1d, ediff1d, + apply_over_axes, apply_along_axis, + compress_rowcols, mask_rowcols, + clump_masked, clump_unmasked, + flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges, + masked_all, masked_all_like) class TestGeneric(TestCase): @@ -53,7 +62,6 @@ class TestGeneric(TestCase): control = array([[(1, (1, 1))]], mask=[[(1, (1, 1))]], dtype=dt) assert_equal(test, control) - def test_masked_all_like(self): "Tests masked_all" # Standard dtype @@ -132,10 +140,10 @@ class TestAverage(TestCase): "More tests of average." w1 = [0, 1, 1, 1, 1, 0] w2 = [[0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 0, 1]] - x = arange(6, dtype=float_) + x = arange(6, dtype=np.float_) assert_equal(average(x, axis=0), 2.5) assert_equal(average(x, axis=0, weights=w1), 2.5) - y = array([arange(6, dtype=float_), 2.0 * arange(6)]) + y = array([arange(6, dtype=np.float_), 2.0 * arange(6)]) assert_equal(average(y, None), np.add.reduce(np.arange(6)) * 3. / 12.) assert_equal(average(y, axis=0), np.arange(6) * 3. / 2.) assert_equal(average(y, axis=1), @@ -167,12 +175,12 @@ class TestAverage(TestCase): a = arange(6) b = arange(6) * 3 r1, w1 = average([[a, b], [b, a]], axis=1, returned=1) - assert_equal(shape(r1) , shape(w1)) - assert_equal(r1.shape , w1.shape) + assert_equal(shape(r1), shape(w1)) + assert_equal(r1.shape, w1.shape) r2, w2 = average(ones((2, 2, 3)), axis=0, weights=[3, 1], returned=1) - assert_equal(shape(w2) , shape(r2)) + assert_equal(shape(w2), shape(r2)) r2, w2 = average(ones((2, 2, 3)), returned=1) - assert_equal(shape(w2) , shape(r2)) + assert_equal(shape(w2), shape(r2)) r2, w2 = average(ones((2, 2, 3)), weights=ones((2, 2, 3)), returned=1) assert_equal(shape(w2), shape(r2)) a2d = array([[1, 2], [0, 4]], float) @@ -193,6 +201,50 @@ class TestAverage(TestCase): a = average(array([1, 2, 3, 4], mask=[False, False, True, True])) assert_equal(a, 1.5) + def test_complex(self): + # Test with complex data. + # (Regression test for https://github.com/numpy/numpy/issues/2684) + mask = np.array([[0, 0, 0, 1, 0], + [0, 1, 0, 0, 0]], dtype=bool) + a = masked_array([[0, 1+2j, 3+4j, 5+6j, 7+8j], + [9j, 0+1j, 2+3j, 4+5j, 7+7j]], + mask=mask) + + av = average(a) + expected = np.average(a.compressed()) + assert_almost_equal(av.real, expected.real) + assert_almost_equal(av.imag, expected.imag) + + av0 = average(a, axis=0) + expected0 = average(a.real, axis=0) + average(a.imag, axis=0)*1j + assert_almost_equal(av0.real, expected0.real) + assert_almost_equal(av0.imag, expected0.imag) + + av1 = average(a, axis=1) + expected1 = average(a.real, axis=1) + average(a.imag, axis=1)*1j + assert_almost_equal(av1.real, expected1.real) + assert_almost_equal(av1.imag, expected1.imag) + + # Test with the 'weights' argument. + wts = np.array([[0.5, 1.0, 2.0, 1.0, 0.5], + [1.0, 1.0, 1.0, 1.0, 1.0]]) + wav = average(a, weights=wts) + expected = np.average(a.compressed(), weights=wts[~mask]) + assert_almost_equal(wav.real, expected.real) + assert_almost_equal(wav.imag, expected.imag) + + wav0 = average(a, weights=wts, axis=0) + expected0 = (average(a.real, weights=wts, axis=0) + + average(a.imag, weights=wts, axis=0)*1j) + assert_almost_equal(wav0.real, expected0.real) + assert_almost_equal(wav0.imag, expected0.imag) + + wav1 = average(a, weights=wts, axis=1) + expected1 = (average(a.real, weights=wts, axis=1) + + average(a.imag, weights=wts, axis=1)*1j) + assert_almost_equal(wav1.real, expected1.real) + assert_almost_equal(wav1.imag, expected1.imag) + class TestConcatenator(TestCase): """ @@ -206,7 +258,7 @@ class TestConcatenator(TestCase): m = [1, 0, 0, 0, 0] d = masked_array(b, mask=m) c = mr_[d, 0, 0, d] - self.assertTrue(isinstance(c, MaskedArray) or isinstance(c, core.MaskedArray)) + self.assertTrue(isinstance(c, MaskedArray)) assert_array_equal(c, [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1]) assert_array_equal(c.mask, mr_[m, 0, 0, m]) @@ -230,7 +282,6 @@ class TestConcatenator(TestCase): assert_array_equal(d.mask, np.r_[m_1, m_2]) - class TestNotMasked(TestCase): """ Tests notmasked_edges and notmasked_contiguous. @@ -270,7 +321,6 @@ class TestNotMasked(TestCase): assert_equal(test[0], [(0, 1, 2, 4), (0, 0, 2, 3)]) assert_equal(test[1], [(0, 1, 2, 4), (4, 2, 4, 4)]) - def test_contiguous(self): "Tests notmasked_contiguous" a = masked_array(np.arange(24).reshape(3, 8), @@ -295,12 +345,12 @@ class TestNotMasked(TestCase): assert_equal(tmp[2][-2], slice(0, 6, None)) - class Test2DFunctions(TestCase): "Tests 2D functions" def test_compress2d(self): "Tests compress2d" - x = array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]]) + x = array(np.arange(9).reshape(3, 3), + mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]]) assert_equal(compress_rowcols(x), [[4, 5], [7, 8]]) assert_equal(compress_rowcols(x, 0), [[3, 4, 5], [6, 7, 8]]) assert_equal(compress_rowcols(x, 1), [[1, 2], [4, 5], [7, 8]]) @@ -316,21 +366,31 @@ class Test2DFunctions(TestCase): assert_equal(compress_rowcols(x).size, 0) assert_equal(compress_rowcols(x, 0).size, 0) assert_equal(compress_rowcols(x, 1).size, 0) - # + def test_mask_rowcols(self): "Tests mask_rowcols." - x = array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]]) - assert_equal(mask_rowcols(x).mask, [[1, 1, 1], [1, 0, 0], [1, 0, 0]]) - assert_equal(mask_rowcols(x, 0).mask, [[1, 1, 1], [0, 0, 0], [0, 0, 0]]) - assert_equal(mask_rowcols(x, 1).mask, [[1, 0, 0], [1, 0, 0], [1, 0, 0]]) + x = array(np.arange(9).reshape(3, 3), + mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]]) + assert_equal(mask_rowcols(x).mask, + [[1, 1, 1], [1, 0, 0], [1, 0, 0]]) + assert_equal(mask_rowcols(x, 0).mask, + [[1, 1, 1], [0, 0, 0], [0, 0, 0]]) + assert_equal(mask_rowcols(x, 1).mask, + [[1, 0, 0], [1, 0, 0], [1, 0, 0]]) x = array(x._data, mask=[[0, 0, 0], [0, 1, 0], [0, 0, 0]]) - assert_equal(mask_rowcols(x).mask, [[0, 1, 0], [1, 1, 1], [0, 1, 0]]) - assert_equal(mask_rowcols(x, 0).mask, [[0, 0, 0], [1, 1, 1], [0, 0, 0]]) - assert_equal(mask_rowcols(x, 1).mask, [[0, 1, 0], [0, 1, 0], [0, 1, 0]]) + assert_equal(mask_rowcols(x).mask, + [[0, 1, 0], [1, 1, 1], [0, 1, 0]]) + assert_equal(mask_rowcols(x, 0).mask, + [[0, 0, 0], [1, 1, 1], [0, 0, 0]]) + assert_equal(mask_rowcols(x, 1).mask, + [[0, 1, 0], [0, 1, 0], [0, 1, 0]]) x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 0]]) - assert_equal(mask_rowcols(x).mask, [[1, 1, 1], [1, 1, 1], [1, 1, 0]]) - assert_equal(mask_rowcols(x, 0).mask, [[1, 1, 1], [1, 1, 1], [0, 0, 0]]) - assert_equal(mask_rowcols(x, 1,).mask, [[1, 1, 0], [1, 1, 0], [1, 1, 0]]) + assert_equal(mask_rowcols(x).mask, + [[1, 1, 1], [1, 1, 1], [1, 1, 0]]) + assert_equal(mask_rowcols(x, 0).mask, + [[1, 1, 1], [1, 1, 1], [0, 0, 0]]) + assert_equal(mask_rowcols(x, 1,).mask, + [[1, 1, 0], [1, 1, 0], [1, 1, 0]]) x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) self.assertTrue(mask_rowcols(x).all() is masked) self.assertTrue(mask_rowcols(x, 0).all() is masked) @@ -338,7 +398,7 @@ class Test2DFunctions(TestCase): self.assertTrue(mask_rowcols(x).mask.all()) self.assertTrue(mask_rowcols(x, 0).mask.all()) self.assertTrue(mask_rowcols(x, 1).mask.all()) - # + def test_dot(self): "Tests dot product" n = np.arange(1, 7) @@ -410,9 +470,7 @@ class Test2DFunctions(TestCase): assert_equal(c, np.dot(b.filled(0), a.filled(0))) - class TestApplyAlongAxis(TestCase): - # "Tests 2D functions" def test_3d(self): a = arange(12.).reshape(2, 2, 3) @@ -422,21 +480,20 @@ class TestApplyAlongAxis(TestCase): assert_equal(xa, [[1, 4], [7, 10]]) - class TestApplyOverAxes(TestCase): "Tests apply_over_axes" def test_basic(self): a = arange(24).reshape(2, 3, 4) test = apply_over_axes(np.sum, a, [0, 2]) - ctrl = np.array([[[ 60], [ 92], [124]]]) + ctrl = np.array([[[60], [92], [124]]]) assert_equal(test, ctrl) a[(a % 2).astype(np.bool)] = masked test = apply_over_axes(np.sum, a, [0, 2]) - ctrl = np.array([[[ 30], [ 44], [60]]]) + ctrl = np.array([[[30], [44], [60]]]) class TestMedian(TestCase): - # + def test_2d(self): "Tests median w/ 2D" (n, p) = (101, 30) @@ -452,7 +509,7 @@ class TestMedian(TestCase): assert_equal(median(z), 0) assert_equal(median(z, axis=0), np.zeros(p)) assert_equal(median(z.T, axis=1), np.zeros(p)) - # + def test_2d_waxis(self): "Tests median w/ 2D arrays and different axis." x = masked_array(np.arange(30).reshape(10, 3)) @@ -461,7 +518,7 @@ class TestMedian(TestCase): assert_equal(median(x, axis=0), [13.5, 14.5, 15.5]) assert_equal(median(x, axis=1), [0, 0, 0, 10, 13, 16, 19, 0, 0, 0]) assert_equal(median(x, axis=1).mask, [1, 1, 1, 0, 0, 0, 0, 1, 1, 1]) - # + def test_3d(self): "Tests median w/ 3D" x = np.ma.arange(24).reshape(3, 4, 2) @@ -474,7 +531,6 @@ class TestMedian(TestCase): assert_equal(median(x, 0), [[12, 10], [8, 9], [16, 17]]) - class TestCov(TestCase): def setUp(self): @@ -528,16 +584,18 @@ class TestCov(TestCase): valid = np.logical_not(getmaskarray(x)).astype(int) frac = np.dot(valid, valid.T) xf = (x - x.mean(1)[:, None]).filled(0) - assert_almost_equal(cov(x), np.cov(xf) * (x.shape[1] - 1) / (frac - 1.)) + assert_almost_equal(cov(x), + np.cov(xf) * (x.shape[1] - 1) / (frac - 1.)) assert_almost_equal(cov(x, bias=True), np.cov(xf, bias=True) * x.shape[1] / frac) frac = np.dot(valid.T, valid) xf = (x - x.mean(0)).filled(0) assert_almost_equal(cov(x, rowvar=False), - np.cov(xf, rowvar=False) * (x.shape[0] - 1) / (frac - 1.)) + (np.cov(xf, rowvar=False) * + (x.shape[0] - 1) / (frac - 1.))) assert_almost_equal(cov(x, rowvar=False, bias=True), - np.cov(xf, rowvar=False, bias=True) * x.shape[0] / frac) - + (np.cov(xf, rowvar=False, bias=True) * + x.shape[0] / frac)) class TestCorrcoef(TestCase): @@ -550,7 +608,6 @@ class TestCorrcoef(TestCase): x = self.data assert_almost_equal(np.corrcoef(x, ddof=0), corrcoef(x, ddof=0)) - def test_1d_wo_missing(self): "Test cov on 1D variable w/o missing values" x = self.data @@ -576,7 +633,8 @@ class TestCorrcoef(TestCase): x -= x.mean() nx = x.compressed() assert_almost_equal(np.corrcoef(nx), corrcoef(x)) - assert_almost_equal(np.corrcoef(nx, rowvar=False), corrcoef(x, rowvar=False)) + assert_almost_equal(np.corrcoef(nx, rowvar=False), + corrcoef(x, rowvar=False)) assert_almost_equal(np.corrcoef(nx, rowvar=False, bias=True), corrcoef(x, rowvar=False, bias=True)) # @@ -604,7 +662,6 @@ class TestCorrcoef(TestCase): assert_almost_equal(test[:-1, :-1], control[:-1, :-1]) - class TestPolynomial(TestCase): # def test_polyfit(self): @@ -620,7 +677,8 @@ class TestPolynomial(TestCase): y[0, 0] = y[-1, -1] = masked # (C, R, K, S, D) = polyfit(x, y[:, 0], 3, full=True) - (c, r, k, s, d) = np.polyfit(x[1:], y[1:, 0].compressed(), 3, full=True) + (c, r, k, s, d) = np.polyfit(x[1:], y[1:, 0].compressed(), 3, + full=True) for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)): assert_almost_equal(a, a_) # @@ -634,7 +692,7 @@ class TestPolynomial(TestCase): for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)): assert_almost_equal(a, a_) # - w = np.random.rand(10) + 1 + w = np.random.rand(10) + 1 wo = w.copy() xs = x[1:-1] ys = y[1:-1] @@ -647,7 +705,7 @@ class TestPolynomial(TestCase): class TestArraySetOps(TestCase): - # + def test_unique_onlist(self): "Test unique on list" data = [1, 1, 1, 2, 2, 3] @@ -696,7 +754,7 @@ class TestArraySetOps(TestCase): assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + def test_ediff1d_tobegin(self): "Test ediff1d w/ to_begin" x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1]) @@ -711,7 +769,7 @@ class TestArraySetOps(TestCase): assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + def test_ediff1d_toend(self): "Test ediff1d w/ to_end" x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1]) @@ -726,7 +784,7 @@ class TestArraySetOps(TestCase): assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + def test_ediff1d_tobegin_toend(self): "Test ediff1d w/ to_begin and to_end" x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1]) @@ -737,11 +795,12 @@ class TestArraySetOps(TestCase): assert_equal(test.mask, control.mask) # test = ediff1d(x, to_end=[1, 2, 3], to_begin=masked) - control = array([0, 1, 1, 1, 4, 1, 2, 3], mask=[1, 1, 0, 0, 1, 0, 0, 0]) + control = array([0, 1, 1, 1, 4, 1, 2, 3], + mask=[1, 1, 0, 0, 1, 0, 0, 0]) assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + def test_ediff1d_ndarray(self): "Test ediff1d w/ a ndarray" x = np.arange(5) @@ -758,7 +817,6 @@ class TestArraySetOps(TestCase): assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - def test_intersect1d(self): "Test intersect1d" x = array([1, 3, 3, 3], mask=[0, 0, 0, 1]) @@ -767,7 +825,6 @@ class TestArraySetOps(TestCase): control = array([1, 3, -1], mask=[0, 0, 1]) assert_equal(test, control) - def test_setxor1d(self): "Test setxor1d" a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1]) @@ -794,7 +851,6 @@ class TestArraySetOps(TestCase): # assert_array_equal([], setxor1d([], [])) - def test_in1d(self): "Test in1d" a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1]) @@ -809,7 +865,6 @@ class TestArraySetOps(TestCase): # assert_array_equal([], in1d([], [])) - def test_in1d_invert(self): "Test in1d's invert parameter" a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1]) @@ -822,7 +877,6 @@ class TestArraySetOps(TestCase): assert_array_equal([], in1d([], [], invert=True)) - def test_union1d(self): "Test union1d" a = array([1, 2, 5, 7, 5, -1], mask=[0, 0, 0, 0, 0, 1]) @@ -833,7 +887,6 @@ class TestArraySetOps(TestCase): # assert_array_equal([], union1d([], [])) - def test_setdiff1d(self): "Test setdiff1d" a = array([6, 5, 4, 7, 7, 1, 2, 1], mask=[0, 0, 0, 0, 0, 0, 0, 1]) @@ -845,7 +898,6 @@ class TestArraySetOps(TestCase): b = arange(8) assert_equal(setdiff1d(a, b), array([8, 9])) - def test_setdiff1d_char_array(self): "Test setdiff1d_charray" a = np.array(['a', 'b', 'c']) @@ -853,9 +905,6 @@ class TestArraySetOps(TestCase): assert_array_equal(setdiff1d(a, b), np.array(['c'])) - - - class TestShapeBase(TestCase): # def test_atleast2d(self): |