Skip to content

Commit 7984bd4

Browse files
authored
REF: share Datetimelike argmin/min etc with Index (#42150)
1 parent 9a5da9b commit 7984bd4

File tree

2 files changed

+81
-115
lines changed

2 files changed

+81
-115
lines changed

pandas/core/indexes/base.py

+81
Original file line numberDiff line numberDiff line change
@@ -6050,6 +6050,9 @@ def __inv__(self):
60506050
# TODO: __inv__ vs __invert__?
60516051
return self._unary_method(lambda x: -x)
60526052

6053+
# --------------------------------------------------------------------
6054+
# Reductions
6055+
60536056
def any(self, *args, **kwargs):
60546057
"""
60556058
Return whether any element is Truthy.
@@ -6170,6 +6173,84 @@ def _maybe_disable_logical_methods(self, opname: str_t):
61706173
# This call will raise
61716174
make_invalid_op(opname)(self)
61726175

6176+
@Appender(IndexOpsMixin.argmin.__doc__)
6177+
def argmin(self, axis=None, skipna=True, *args, **kwargs):
6178+
nv.validate_argmin(args, kwargs)
6179+
nv.validate_minmax_axis(axis)
6180+
6181+
if not self._is_multi and self.hasnans:
6182+
# Take advantage of cache
6183+
mask = self._isnan
6184+
if not skipna or mask.all():
6185+
return -1
6186+
return super().argmin(skipna=skipna)
6187+
6188+
@Appender(IndexOpsMixin.argmax.__doc__)
6189+
def argmax(self, axis=None, skipna=True, *args, **kwargs):
6190+
nv.validate_argmax(args, kwargs)
6191+
nv.validate_minmax_axis(axis)
6192+
6193+
if not self._is_multi and self.hasnans:
6194+
# Take advantage of cache
6195+
mask = self._isnan
6196+
if not skipna or mask.all():
6197+
return -1
6198+
return super().argmax(skipna=skipna)
6199+
6200+
@doc(IndexOpsMixin.min)
6201+
def min(self, axis=None, skipna=True, *args, **kwargs):
6202+
nv.validate_min(args, kwargs)
6203+
nv.validate_minmax_axis(axis)
6204+
6205+
if not len(self):
6206+
return self._na_value
6207+
6208+
if len(self) and self.is_monotonic_increasing:
6209+
# quick check
6210+
first = self[0]
6211+
if not isna(first):
6212+
return first
6213+
6214+
if not self._is_multi and self.hasnans:
6215+
# Take advantage of cache
6216+
mask = self._isnan
6217+
if not skipna or mask.all():
6218+
return self._na_value
6219+
6220+
if not self._is_multi and not isinstance(self._values, np.ndarray):
6221+
# "ExtensionArray" has no attribute "min"
6222+
return self._values.min(skipna=skipna) # type: ignore[attr-defined]
6223+
6224+
return super().min(skipna=skipna)
6225+
6226+
@doc(IndexOpsMixin.max)
6227+
def max(self, axis=None, skipna=True, *args, **kwargs):
6228+
nv.validate_max(args, kwargs)
6229+
nv.validate_minmax_axis(axis)
6230+
6231+
if not len(self):
6232+
return self._na_value
6233+
6234+
if len(self) and self.is_monotonic_increasing:
6235+
# quick check
6236+
last = self[-1]
6237+
if not isna(last):
6238+
return last
6239+
6240+
if not self._is_multi and self.hasnans:
6241+
# Take advantage of cache
6242+
mask = self._isnan
6243+
if not skipna or mask.all():
6244+
return self._na_value
6245+
6246+
if not self._is_multi and not isinstance(self._values, np.ndarray):
6247+
# "ExtensionArray" has no attribute "max"
6248+
return self._values.max(skipna=skipna) # type: ignore[attr-defined]
6249+
6250+
return super().max(skipna=skipna)
6251+
6252+
# --------------------------------------------------------------------
6253+
61736254
@final
61746255
@property
61756256
def shape(self) -> Shape:

pandas/core/indexes/datetimelike.py

-115
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from pandas._libs import (
1919
NaT,
2020
Timedelta,
21-
iNaT,
2221
lib,
2322
)
2423
from pandas._libs.tslibs import (
@@ -198,120 +197,6 @@ def tolist(self) -> list:
198197
"""
199198
return list(self.astype(object))
200199

201-
def min(self, axis=None, skipna=True, *args, **kwargs):
202-
"""
203-
Return the minimum value of the Index or minimum along
204-
an axis.
205-
206-
See Also
207-
--------
208-
numpy.ndarray.min
209-
Series.min : Return the minimum value in a Series.
210-
"""
211-
nv.validate_min(args, kwargs)
212-
nv.validate_minmax_axis(axis)
213-
214-
if not len(self):
215-
return self._na_value
216-
217-
i8 = self.asi8
218-
219-
if len(i8) and self.is_monotonic_increasing:
220-
# quick check
221-
if i8[0] != iNaT:
222-
return self._data._box_func(i8[0])
223-
224-
if self.hasnans:
225-
if not skipna:
226-
return self._na_value
227-
i8 = i8[~self._isnan]
228-
229-
if not len(i8):
230-
return self._na_value
231-
232-
min_stamp = i8.min()
233-
return self._data._box_func(min_stamp)
234-
235-
def argmin(self, axis=None, skipna=True, *args, **kwargs):
236-
"""
237-
Returns the indices of the minimum values along an axis.
238-
239-
See `numpy.ndarray.argmin` for more information on the
240-
`axis` parameter.
241-
242-
See Also
243-
--------
244-
numpy.ndarray.argmin
245-
"""
246-
nv.validate_argmin(args, kwargs)
247-
nv.validate_minmax_axis(axis)
248-
249-
i8 = self.asi8
250-
if self.hasnans:
251-
mask = self._isnan
252-
if mask.all() or not skipna:
253-
return -1
254-
i8 = i8.copy()
255-
i8[mask] = np.iinfo("int64").max
256-
return i8.argmin()
257-
258-
def max(self, axis=None, skipna=True, *args, **kwargs):
259-
"""
260-
Return the maximum value of the Index or maximum along
261-
an axis.
262-
263-
See Also
264-
--------
265-
numpy.ndarray.max
266-
Series.max : Return the maximum value in a Series.
267-
"""
268-
nv.validate_max(args, kwargs)
269-
nv.validate_minmax_axis(axis)
270-
271-
if not len(self):
272-
return self._na_value
273-
274-
i8 = self.asi8
275-
276-
if len(i8) and self.is_monotonic:
277-
# quick check
278-
if i8[-1] != iNaT:
279-
return self._data._box_func(i8[-1])
280-
281-
if self.hasnans:
282-
if not skipna:
283-
return self._na_value
284-
i8 = i8[~self._isnan]
285-
286-
if not len(i8):
287-
return self._na_value
288-
289-
max_stamp = i8.max()
290-
return self._data._box_func(max_stamp)
291-
292-
def argmax(self, axis=None, skipna=True, *args, **kwargs):
293-
"""
294-
Returns the indices of the maximum values along an axis.
295-
296-
See `numpy.ndarray.argmax` for more information on the
297-
`axis` parameter.
298-
299-
See Also
300-
--------
301-
numpy.ndarray.argmax
302-
"""
303-
nv.validate_argmax(args, kwargs)
304-
nv.validate_minmax_axis(axis)
305-
306-
i8 = self.asi8
307-
if self.hasnans:
308-
mask = self._isnan
309-
if mask.all() or not skipna:
310-
return -1
311-
i8 = i8.copy()
312-
i8[mask] = 0
313-
return i8.argmax()
314-
315200
# --------------------------------------------------------------------
316201
# Rendering Methods
317202

0 commit comments

Comments
 (0)