Skip to content

Commit 10caf75

Browse files
committed
Merge pull request numpy#7382 from ahaldane/tidy_average_median
MAINT: cleanup np.average
2 parents 8c4048a + 5ceab8f commit 10caf75

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

numpy/lib/function_base.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -898,15 +898,19 @@ def average(a, axis=None, weights=None, returned=False):
898898
TypeError: Axis must be specified when shapes of a and weights differ.
899899
900900
"""
901-
if not isinstance(a, np.matrix):
902-
a = np.asarray(a)
901+
a = np.asanyarray(a)
903902

904903
if weights is None:
905904
avg = a.mean(axis)
906905
scl = avg.dtype.type(a.size/avg.size)
907906
else:
908-
a = a + 0.0
909-
wgt = np.asarray(weights)
907+
wgt = np.asanyarray(weights)
908+
909+
if issubclass(a.dtype.type, (np.integer, np.bool_)):
910+
result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')
911+
else:
912+
result_dtype = np.result_type(a.dtype, wgt.dtype)
913+
910914
# Sanity checks
911915
if a.shape != wgt.shape:
912916
if axis is None:
@@ -921,17 +925,18 @@ def average(a, axis=None, weights=None, returned=False):
921925
"Length of weights not compatible with specified axis.")
922926

923927
# setup wgt to broadcast along axis
924-
wgt = np.array(wgt, copy=0, ndmin=a.ndim).swapaxes(-1, axis)
928+
wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape)
929+
wgt = wgt.swapaxes(-1, axis)
925930

926-
scl = wgt.sum(axis=axis, dtype=np.result_type(a.dtype, wgt.dtype))
931+
scl = wgt.sum(axis=axis, dtype=result_dtype)
927932
if (scl == 0.0).any():
928933
raise ZeroDivisionError(
929934
"Weights sum to zero, can't be normalized")
930935

931-
avg = np.multiply(a, wgt).sum(axis)/scl
936+
avg = np.multiply(a, wgt, dtype=result_dtype).sum(axis)/scl
932937

933938
if returned:
934-
scl = np.multiply(avg, 0) + scl
939+
scl = np.broadcast_to(scl, avg.shape)
935940
return avg, scl
936941
else:
937942
return avg

numpy/lib/tests/test_function_base.py

+23
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,29 @@ def test_returned(self):
167167
avg, scl = average(y, weights=w2, axis=1, returned=True)
168168
assert_array_equal(scl, np.array([1., 6.]))
169169

170+
def test_subclasses(self):
171+
class subclass(np.ndarray):
172+
pass
173+
a = np.array([[1,2],[3,4]]).view(subclass)
174+
w = np.array([[1,2],[3,4]]).view(subclass)
175+
176+
assert_equal(type(np.average(a, weights=w)), subclass)
177+
178+
# also test matrices
179+
a = np.matrix([[1,2],[3,4]])
180+
w = np.matrix([[1,2],[3,4]])
181+
182+
r = np.average(a, axis=0, weights=w)
183+
assert_equal(type(r), np.matrix)
184+
assert_equal(r, [[2.5, 10.0/3]])
185+
186+
def test_upcasting(self):
187+
types = [('i4', 'i4', 'f8'), ('i4', 'f4', 'f8'), ('f4', 'i4', 'f8'),
188+
('f4', 'f4', 'f4'), ('f4', 'f8', 'f8')]
189+
for at, wt, rt in types:
190+
a = np.array([[1,2],[3,4]], dtype=at)
191+
w = np.array([[1,2],[3,4]], dtype=wt)
192+
assert_equal(np.average(a, weights=w).dtype, np.dtype(rt))
170193

171194
class TestSelect(TestCase):
172195
choices = [np.array([1, 2, 3]),

0 commit comments

Comments
 (0)