diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 58529c5597b6e..11e71a80b9dee 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -36,9 +36,7 @@ NullFrequencyError, ) from pandas.util._decorators import ( - Appender, cache_readonly, - doc, ) from pandas.core.dtypes.common import ( @@ -57,12 +55,10 @@ PeriodArray, TimedeltaArray, ) -from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin import pandas.core.common as com import pandas.core.indexes.base as ibase from pandas.core.indexes.base import ( Index, - _index_shared_docs, ) from pandas.core.indexes.extension import NDArrayBackedExtensionIndex from pandas.core.indexes.range import RangeIndex @@ -92,8 +88,37 @@ class DatetimeIndexOpsMixin(NDArrayBackedExtensionIndex, ABC): _can_hold_strings = False _data: DatetimeArray | TimedeltaArray | PeriodArray - @doc(DatetimeLikeArrayMixin.mean) def mean(self, *, skipna: bool = True, axis: int | None = 0): + """ + Return the mean value of the Array. + + Parameters + ---------- + skipna : bool, default True + Whether to ignore any NaT elements. + axis : int, optional, default 0 + Axis along which to compute the mean. + + Returns + ------- + scalar + Timestamp or Timedelta. + + See Also + -------- + numpy.ndarray.mean : Returns the average of the array elements. + Series.mean : Return the mean value in a Series. + + Examples + -------- + >>> idx = pd.date_range("2023-01-01", periods=3) + >>> idx.mean() + Timestamp('2023-01-02 00:00:00') + + >>> idx = pd.to_timedelta([1, 2, 3], unit="D") + >>> idx.mean() + Timedelta('2 days 00:00:00') + """ return self._data.mean(skipna=skipna, axis=axis) @property @@ -136,8 +161,22 @@ def asi8(self) -> npt.NDArray[np.int64]: return self._data.asi8 @property - @doc(DatetimeLikeArrayMixin.freqstr) def freqstr(self) -> str: + """ + Return the frequency string if it is set, otherwise None. + + See Also + -------- + DatetimeIndex.freq : Return the frequency object if it is set, otherwise None. + DatetimeIndex.inferred_freq : Tries to return a string representing a frequency + guess generated by infer_freq. + + Examples + -------- + >>> idx = pd.date_range("2023-01-01", periods=3, freq="D") + >>> idx.freqstr + 'D' + """ from pandas import PeriodIndex if self._data.freqstr is not None and isinstance( @@ -153,8 +192,15 @@ def freqstr(self) -> str: def _resolution_obj(self) -> Resolution: ... @cache_readonly - @doc(DatetimeLikeArrayMixin.resolution) def resolution(self) -> str: + """ + Return the resolution of the array. + + Returns + ------- + str + The resolution of the array. + """ return self._data.resolution # ------------------------------------------------------------------------ @@ -199,8 +245,10 @@ def equals(self, other: Any) -> bool: return np.array_equal(self.asi8, other.asi8) - @Appender(Index.__contains__.__doc__) def __contains__(self, key: Any) -> bool: + """ + Return True if the key is in the Index. + """ hash(key) try: self.get_loc(key) @@ -243,8 +291,10 @@ def _format_attrs(self): attrs.append(("freq", freq)) return attrs - @Appender(Index._summary.__doc__) def _summary(self, name=None) -> str: + """ + Return a summary of the Index. + """ result = super()._summary(name=name) if self.freq: result += f"\nFreq: {self.freqstr}" @@ -405,8 +455,20 @@ def shift(self, periods: int = 1, freq=None) -> Self: # -------------------------------------------------------------------- - @doc(Index._maybe_cast_listlike_indexer) def _maybe_cast_listlike_indexer(self, keyarr): + """ + Ensure that the list-like indexer is of the correct type. + + Parameters + ---------- + keyarr : list-like + The list-like indexer to check. + + Returns + ------- + list-like + The list-like indexer of the correct type. + """ try: res = self._data._validate_listlike(keyarr, allow_object=True) except (ValueError, TypeError): @@ -497,8 +559,33 @@ def values(self) -> np.ndarray: data.flags.writeable = False return data - @doc(DatetimeIndexOpsMixin.shift) def shift(self, periods: int = 1, freq=None) -> Self: + """ + Shift index by desired number of time frequency increments. + + This method is for shifting the values of datetime-like indexes + by a specified time increment a given number of times. + + Parameters + ---------- + periods : int, default 1 + Number of periods (or increments) to shift by, + can be positive or negative. + freq : pandas.DateOffset, pandas.Timedelta or string, optional + Frequency increment to shift by. + If None, the index is shifted by its own `freq` attribute. + Offset aliases are valid strings, e.g., 'D', 'W', 'M' etc. + + Returns + ------- + pandas.DatetimeIndex + Shifted index. + + See Also + -------- + Index.shift : Shift values of Index. + PeriodIndex.shift : Shift values of PeriodIndex. + """ if freq is not None and freq != self.freq: if isinstance(freq, str): freq = to_offset(freq) @@ -524,8 +611,25 @@ def shift(self, periods: int = 1, freq=None) -> Self: return type(self)._simple_new(result, name=self.name) @cache_readonly - @doc(DatetimeLikeArrayMixin.inferred_freq) def inferred_freq(self) -> str | None: + """ + Tries to return a string representing a frequency guess generated by infer_freq. + + Returns + ------- + str or None + + See Also + -------- + DatetimeIndex.freq : Return the frequency object if it is set, otherwise None. + DatetimeIndex.freqstr : Return the frequency string if it is set. + + Examples + -------- + >>> idx = pd.DatetimeIndex(["2018-01-01", "2018-01-03", "2018-01-05"]) + >>> idx.inferred_freq + '2D' + """ return self._data.inferred_freq # -------------------------------------------------------------------- @@ -816,14 +920,41 @@ def _get_insert_freq(self, loc: int, item): freq = self.freq return freq - @doc(NDArrayBackedExtensionIndex.delete) def delete(self, loc) -> Self: + """ + Make new Index with passed location(-s) deleted. + + Parameters + ---------- + loc : int or list of int + Location of item(-s) to delete. Use a list of locations to delete + multiple items. If a slice is provided, the step must be 1. + + Returns + ------- + Index + Will be same type as self, except for RangeIndex. + """ result = super().delete(loc) result._data._freq = self._get_delete_freq(loc) return result - @doc(NDArrayBackedExtensionIndex.insert) def insert(self, loc: int, item): + """ + Make new Index inserting new item at location. + + Follows Python list.insert semantics for negative values. Only at + least one of the index/item pairs must be specified. + + Parameters + ---------- + loc : int + item : object + + Returns + ------- + Index + """ result = super().insert(loc, item) if isinstance(result, type(self)): # i.e. parent class method did not cast @@ -833,7 +964,6 @@ def insert(self, loc: int, item): # -------------------------------------------------------------------- # NDArray-Like Methods - @Appender(_index_shared_docs["take"] % _index_doc_kwargs) def take( self, indices, @@ -842,6 +972,32 @@ def take( fill_value=None, **kwargs, ) -> Self: + """ + Return a new Index of the values selected by the indices. + + For internal compatibility with numpy arrays. + + Parameters + ---------- + indices : array-like + Indices to be taken. + axis : int, optional + The axis over which to select values. Always 0. + allow_fill : bool, default True + fill_value : scalar, default None + If allow_fill=True and fill_value is not None, this value is used + instead of raising if the index is out of bounds. + + Returns + ------- + Index + An element of same type as self. + + See Also + -------- + numpy.ndarray.take : Return an array formed from the elements of a + at the given indices. + """ nv.validate_take((), kwargs) indices = np.asarray(indices, dtype=np.intp)