Skip to content

Commit 862cd05

Browse files
authored
TYP: datetimelike (#38307)
1 parent 0a0cf7b commit 862cd05

File tree

4 files changed

+38
-27
lines changed

4 files changed

+38
-27
lines changed

pandas/core/arrays/datetimelike.py

+31-21
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@ def __init__(self, data, dtype=None, freq=None, copy=False):
112112

113113
@classmethod
114114
def _simple_new(
115-
cls, values: np.ndarray, freq: Optional[BaseOffset] = None, dtype=None
116-
):
115+
cls: Type[DatetimeLikeArrayT],
116+
values: np.ndarray,
117+
freq: Optional[BaseOffset] = None,
118+
dtype=None,
119+
) -> DatetimeLikeArrayT:
117120
raise AbstractMethodError(cls)
118121

119122
@property
@@ -217,7 +220,7 @@ def _box_func(self, x):
217220
"""
218221
raise AbstractMethodError(self)
219222

220-
def _box_values(self, values):
223+
def _box_values(self, values) -> np.ndarray:
221224
"""
222225
apply box func to passed values
223226
"""
@@ -416,7 +419,9 @@ def _values_for_factorize(self):
416419
return self._ndarray, iNaT
417420

418421
@classmethod
419-
def _from_factorized(cls, values, original):
422+
def _from_factorized(
423+
cls: Type[DatetimeLikeArrayT], values, original
424+
) -> DatetimeLikeArrayT:
420425
return cls(values, dtype=original.dtype)
421426

422427
# ------------------------------------------------------------------
@@ -661,7 +666,7 @@ def _unbox(
661666
# These are not part of the EA API, but we implement them because
662667
# pandas assumes they're there.
663668

664-
def value_counts(self, dropna=False):
669+
def value_counts(self, dropna: bool = False):
665670
"""
666671
Return a Series containing counts of unique values.
667672
@@ -755,28 +760,30 @@ def isin(self, values) -> np.ndarray:
755760
# ------------------------------------------------------------------
756761
# Null Handling
757762

758-
def isna(self):
763+
def isna(self) -> np.ndarray:
759764
return self._isnan
760765

761766
@property # NB: override with cache_readonly in immutable subclasses
762-
def _isnan(self):
767+
def _isnan(self) -> np.ndarray:
763768
"""
764769
return if each value is nan
765770
"""
766771
return self.asi8 == iNaT
767772

768773
@property # NB: override with cache_readonly in immutable subclasses
769-
def _hasnans(self):
774+
def _hasnans(self) -> np.ndarray:
770775
"""
771776
return if I have any nans; enables various perf speedups
772777
"""
773778
return bool(self._isnan.any())
774779

775-
def _maybe_mask_results(self, result, fill_value=iNaT, convert=None):
780+
def _maybe_mask_results(
781+
self, result: np.ndarray, fill_value=iNaT, convert=None
782+
) -> np.ndarray:
776783
"""
777784
Parameters
778785
----------
779-
result : a ndarray
786+
result : np.ndarray
780787
fill_value : object, default iNaT
781788
convert : str, dtype or None
782789
@@ -794,7 +801,7 @@ def _maybe_mask_results(self, result, fill_value=iNaT, convert=None):
794801
result = result.astype(convert)
795802
if fill_value is None:
796803
fill_value = np.nan
797-
result[self._isnan] = fill_value
804+
np.putmask(result, self._isnan, fill_value)
798805
return result
799806

800807
# ------------------------------------------------------------------
@@ -893,22 +900,24 @@ def _validate_frequency(cls, index, freq, **kwargs):
893900
) from e
894901

895902
@classmethod
896-
def _generate_range(cls, start, end, periods, freq, *args, **kwargs):
903+
def _generate_range(
904+
cls: Type[DatetimeLikeArrayT], start, end, periods, freq, *args, **kwargs
905+
) -> DatetimeLikeArrayT:
897906
raise AbstractMethodError(cls)
898907

899908
# monotonicity/uniqueness properties are called via frequencies.infer_freq,
900909
# see GH#23789
901910

902911
@property
903-
def _is_monotonic_increasing(self):
912+
def _is_monotonic_increasing(self) -> bool:
904913
return algos.is_monotonic(self.asi8, timelike=True)[0]
905914

906915
@property
907-
def _is_monotonic_decreasing(self):
916+
def _is_monotonic_decreasing(self) -> bool:
908917
return algos.is_monotonic(self.asi8, timelike=True)[1]
909918

910919
@property
911-
def _is_unique(self):
920+
def _is_unique(self) -> bool:
912921
return len(unique1d(self.asi8)) == len(self)
913922

914923
# ------------------------------------------------------------------
@@ -940,9 +949,10 @@ def _cmp_method(self, other, op):
940949
result = op(self._ndarray.view("i8"), other_vals.view("i8"))
941950

942951
o_mask = isna(other)
943-
if self._hasnans | np.any(o_mask):
952+
mask = self._isnan | o_mask
953+
if mask.any():
944954
nat_result = op is operator.ne
945-
result[self._isnan | o_mask] = nat_result
955+
np.putmask(result, mask, nat_result)
946956

947957
return result
948958

@@ -996,7 +1006,7 @@ def _add_timedeltalike_scalar(self, other):
9961006
if isna(other):
9971007
# i.e np.timedelta64("NaT"), not recognized by delta_to_nanoseconds
9981008
new_values = np.empty(self.shape, dtype="i8")
999-
new_values[:] = iNaT
1009+
new_values.fill(iNaT)
10001010
return type(self)(new_values, dtype=self.dtype)
10011011

10021012
inc = delta_to_nanoseconds(other)
@@ -1038,7 +1048,7 @@ def _add_timedelta_arraylike(self, other):
10381048
)
10391049
if self._hasnans or other._hasnans:
10401050
mask = self._isnan | other._isnan
1041-
new_values[mask] = iNaT
1051+
np.putmask(new_values, mask, iNaT)
10421052

10431053
return type(self)(new_values, dtype=self.dtype)
10441054

@@ -1053,7 +1063,7 @@ def _add_nat(self):
10531063

10541064
# GH#19124 pd.NaT is treated like a timedelta for both timedelta
10551065
# and datetime dtypes
1056-
result = np.zeros(self.shape, dtype=np.int64)
1066+
result = np.empty(self.shape, dtype=np.int64)
10571067
result.fill(iNaT)
10581068
return type(self)(result, dtype=self.dtype, freq=None)
10591069

@@ -1067,7 +1077,7 @@ def _sub_nat(self):
10671077
# For datetime64 dtypes by convention we treat NaT as a datetime, so
10681078
# this subtraction returns a timedelta64 dtype.
10691079
# For period dtype, timedelta64 is a close-enough return dtype.
1070-
result = np.zeros(self.shape, dtype=np.int64)
1080+
result = np.empty(self.shape, dtype=np.int64)
10711081
result.fill(iNaT)
10721082
return result.view("timedelta64[ns]")
10731083

pandas/core/arrays/datetimes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ def _sub_datetime_arraylike(self, other):
681681
arr_mask = self._isnan | other._isnan
682682
new_values = checked_add_with_arr(self_i8, -other_i8, arr_mask=arr_mask)
683683
if self._hasnans or other._hasnans:
684-
new_values[arr_mask] = iNaT
684+
np.putmask(new_values, arr_mask, iNaT)
685685
return new_values.view("timedelta64[ns]")
686686

687687
def _add_offset(self, offset):

pandas/core/arrays/period.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ def astype(self, dtype, copy: bool = True):
597597
return self.asfreq(dtype.freq)
598598
return super().astype(dtype, copy=copy)
599599

600-
def searchsorted(self, value, side="left", sorter=None):
600+
def searchsorted(self, value, side="left", sorter=None) -> np.ndarray:
601601
value = self._validate_searchsorted_value(value).view("M8[ns]")
602602

603603
# Cast to M8 to get datetime-like NaT placement
@@ -676,7 +676,7 @@ def _addsub_int_array(
676676
other = -other
677677
res_values = algos.checked_add_with_arr(self.asi8, other, arr_mask=self._isnan)
678678
res_values = res_values.view("i8")
679-
res_values[self._isnan] = iNaT
679+
np.putmask(res_values, self._isnan, iNaT)
680680
return type(self)(res_values, freq=self.freq)
681681

682682
def _add_offset(self, other: BaseOffset):

pandas/core/arrays/timedeltas.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ def sum(
383383

384384
def std(
385385
self,
386+
*,
386387
axis=None,
387388
dtype=None,
388389
out=None,
@@ -627,7 +628,7 @@ def __floordiv__(self, other):
627628
# at this point we should only have numeric scalars; anything
628629
# else will raise
629630
result = self.asi8 // other
630-
result[self._isnan] = iNaT
631+
np.putmask(result, self._isnan, iNaT)
631632
freq = None
632633
if self.freq is not None:
633634
# Note: freq gets division, not floor-division
@@ -653,7 +654,7 @@ def __floordiv__(self, other):
653654
mask = self._isnan | other._isnan
654655
if mask.any():
655656
result = result.astype(np.float64)
656-
result[mask] = np.nan
657+
np.putmask(result, mask, np.nan)
657658
return result
658659

659660
elif is_object_dtype(other.dtype):
@@ -707,7 +708,7 @@ def __rfloordiv__(self, other):
707708
mask = self._isnan | other._isnan
708709
if mask.any():
709710
result = result.astype(np.float64)
710-
result[mask] = np.nan
711+
np.putmask(result, mask, np.nan)
711712
return result
712713

713714
elif is_object_dtype(other.dtype):

0 commit comments

Comments
 (0)