Thanks to visit codestin.com
Credit goes to github.com

Skip to content

BUG: (nan)?(arg)?(max|min) handling of NaT inconsistent #5222

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
ischwabacher opened this issue Oct 22, 2014 · 2 comments
Closed

BUG: (nan)?(arg)?(max|min) handling of NaT inconsistent #5222

ischwabacher opened this issue Oct 22, 2014 · 2 comments

Comments

@ischwabacher
Copy link

I would expect the handling of NaT to parallel the handling of NaN: the max or min of an array containing NaT should be NaT, and the argmax or argmin of that array should be the index of the first NaT. Instead, max and min ignore NaT as nanmax and nanmin could be expected to do, while argmax and argmin treat NaT as a minimal element. This inconsistency breaks the invariant that arr[argmin(arr)] == min(arr) (with the additional interpretation that NaN == NaN for this purpose).

To compound this, nanmax and nanmin each raise when applied to m8 or M8 arrays, and nanargmax and nanargmin have the same behavior as argmax and argmin.

In [1]: import numpy as np

In [2]: funcs = [getattr(np, ''.join([nan, arg, which]))
   ...:              for nan in ('', 'nan')
   ...:              for arg in ('', 'arg')
   ...:              for which in ('max', 'min')]

In [3]: arrays = [np.arange(0, 4, dtype=t) for t in ('f8', 'M8[ns]', 'm8[ns]')]

In [4]: for arr in arrays:
   ...:     try:
   ...:         arr[[1, 3]] = 'nan'
   ...:     except ValueError:
   ...:         arr[[1, 3]] = 'nat'
   ...:         

In [5]: for f in funcs:
   ...:     for a in arrays:
   ...:         print('{}(dtype={}) = '.format(f.__name__, a.dtype), end='')
   ...:         try:
   ...:             print(f(a))
   ...:         except Exception as e:
   ...:             print(repr(e))
   ...:             
amax(dtype=float64) = nan
amax(dtype=datetime64[ns]) = 1969-12-31T18:00:00.000000002-0600
amax(dtype=timedelta64[ns]) = 2 nanoseconds
amin(dtype=float64) = nan
amin(dtype=datetime64[ns]) = 1969-12-31T18:00:00.000000000-0600
amin(dtype=timedelta64[ns]) = 0 nanoseconds
argmax(dtype=float64) = 1
argmax(dtype=datetime64[ns]) = 2
argmax(dtype=timedelta64[ns]) = 2
argmin(dtype=float64) = 1
argmin(dtype=datetime64[ns]) = 1
argmin(dtype=timedelta64[ns]) = 1
nanmax(dtype=float64) = 2.0
nanmax(dtype=datetime64[ns]) = TypeError("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",)
nanmax(dtype=timedelta64[ns]) = TypeError("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",)
nanmin(dtype=float64) = 0.0
nanmin(dtype=datetime64[ns]) = TypeError("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",)
nanmin(dtype=timedelta64[ns]) = TypeError("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",)
nanargmax(dtype=float64) = 2
nanargmax(dtype=datetime64[ns]) = 2
nanargmax(dtype=timedelta64[ns]) = 2
nanargmin(dtype=float64) = 0
nanargmin(dtype=datetime64[ns]) = 1
nanargmin(dtype=timedelta64[ns]) = 1
@shoyer
Copy link
Member

shoyer commented May 11, 2016

This inconsistency was mostly resolved by #6031, which made all min/max functions on datetime types skip NaT. It is still true that many of the nan-skipping functions do not support datetime/timedelta.

@bsipocz
Copy link
Member

bsipocz commented Feb 6, 2020

this has fixed now, so I'm closing the issue:

amax(dtype=float64) = nan
amax(dtype=datetime64[ns]) = NaT
amax(dtype=timedelta64[ns]) = NaT
amin(dtype=float64) = nan
amin(dtype=datetime64[ns]) = NaT
amin(dtype=timedelta64[ns]) = NaT
argmax(dtype=float64) = 1
argmax(dtype=datetime64[ns]) = 1
argmax(dtype=timedelta64[ns]) = 1
argmin(dtype=float64) = 1
argmin(dtype=datetime64[ns]) = 1
argmin(dtype=timedelta64[ns]) = 1
nanmax(dtype=float64) = 2.0
nanmax(dtype=datetime64[ns]) = 1970-01-01T00:00:00.000000002
nanmax(dtype=timedelta64[ns]) = 2 nanoseconds
nanmin(dtype=float64) = 0.0
nanmin(dtype=datetime64[ns]) = 1970-01-01T00:00:00.000000000
nanmin(dtype=timedelta64[ns]) = 0 nanoseconds
nanargmax(dtype=float64) = 2
nanargmax(dtype=datetime64[ns]) = 1
nanargmax(dtype=timedelta64[ns]) = 1
nanargmin(dtype=float64) = 0
nanargmin(dtype=datetime64[ns]) = 1
nanargmin(dtype=timedelta64[ns]) = 1

Please do reopen if you think otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants