Skip to content

Commit e61a84b

Browse files
fengluoqiuwufengluoseberg
authored
BUG : avoid maximum fill value of datetime and timedelta return NaT in masked array (numpy#27643)
Fill datetime/timedelta with the correct minimum value for the masked maximum operations. The lowest integer value is NaT, so the actual smallest value is `-2**63+1`. --------- Co-authored-by: fengluo <[email protected]> Co-authored-by: Sebastian Berg <[email protected]>
1 parent fdeb79a commit e61a84b

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

numpy/ma/core.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class MaskError(MAError):
193193

194194
if scalar_dtype.kind in "Mm":
195195
info = np.iinfo(np.int64)
196-
min_val, max_val = info.min, info.max
196+
min_val, max_val = info.min + 1, info.max
197197
elif np.issubdtype(scalar_dtype, np.integer):
198198
info = np.iinfo(sctype)
199199
min_val, max_val = info.min, info.max
@@ -5979,7 +5979,7 @@ def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
59795979
result = masked
59805980
return result
59815981
# Explicit output
5982-
result = self.filled(fill_value).min(axis=axis, out=out, **kwargs)
5982+
self.filled(fill_value).min(axis=axis, out=out, **kwargs)
59835983
if isinstance(out, MaskedArray):
59845984
outmask = getmask(out)
59855985
if outmask is nomask:
@@ -6084,7 +6084,7 @@ def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
60846084
result = masked
60856085
return result
60866086
# Explicit output
6087-
result = self.filled(fill_value).max(axis=axis, out=out, **kwargs)
6087+
self.filled(fill_value).max(axis=axis, out=out, **kwargs)
60886088
if isinstance(out, MaskedArray):
60896089
outmask = getmask(out)
60906090
if outmask is nomask:

numpy/ma/tests/test_core.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,26 @@ def test_minmax_dtypes(self):
13511351
assert masked_array([-cmax, 0], mask=[0, 1]).max() == -cmax
13521352
assert masked_array([cmax, 0], mask=[0, 1]).min() == cmax
13531353

1354+
@pytest.mark.parametrize("time_type", ["M8[s]", "m8[s]"])
1355+
def test_minmax_time_dtypes(self, time_type):
1356+
def minmax_with_mask(arr, mask):
1357+
masked_arr = masked_array(arr, mask=mask)
1358+
expected_min = arr[~np.array(mask, dtype=bool)].min()
1359+
expected_max = arr[~np.array(mask, dtype=bool)].max()
1360+
1361+
assert_array_equal(masked_arr.min(), expected_min)
1362+
assert_array_equal(masked_arr.max(), expected_max)
1363+
1364+
# Additional tests on max/min for time dtypes
1365+
x1 = np.array([1, 1, -2, 4, 5, -10, 10, 1, 2, -2**63+1], dtype=time_type)
1366+
x2 = np.array(['NaT', 1, -2, 4, 5, -10, 10, 1, 2, 3], dtype=time_type)
1367+
x3 = np.array(['NaT', 'NaT', -2, 4, 5, -10, 10, 1, 2, 3], dtype=time_type)
1368+
x_test = [x1, x2, x3]
1369+
m = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
1370+
1371+
for x in x_test:
1372+
minmax_with_mask(x, m)
1373+
13541374
def test_addsumprod(self):
13551375
# Tests add, sum, product.
13561376
(x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d

0 commit comments

Comments
 (0)