27
27
from pandas .compat import set_function_name
28
28
from pandas .compat .numpy import function as nv
29
29
from pandas .errors import AbstractMethodError , NullFrequencyError , PerformanceWarning
30
- from pandas .util ._decorators import Appender , Substitution
30
+ from pandas .util ._decorators import Appender , Substitution , cache_readonly
31
31
from pandas .util ._validators import validate_fillna_kwargs
32
32
33
33
from pandas .core .dtypes .common import (
@@ -175,6 +175,14 @@ def _scalar_from_string(self, value: str) -> DTScalarOrNaT:
175
175
"""
176
176
raise AbstractMethodError (self )
177
177
178
+ @classmethod
179
+ def _rebox_native (cls , value : int ) -> Union [int , np .datetime64 , np .timedelta64 ]:
180
+ """
181
+ Box an integer unboxed via _unbox_scalar into the native type for
182
+ the underlying ndarray.
183
+ """
184
+ raise AbstractMethodError (cls )
185
+
178
186
def _unbox_scalar (self , value : DTScalarOrNaT ) -> int :
179
187
"""
180
188
Unbox the integer value of a scalar `value`.
@@ -458,18 +466,15 @@ class DatetimeLikeArrayMixin(
458
466
# ------------------------------------------------------------------
459
467
# NDArrayBackedExtensionArray compat
460
468
461
- # TODO: make this a cache_readonly; need to get around _index_data
462
- # kludge in libreduction
463
- @property
469
+ @cache_readonly
464
470
def _ndarray (self ) -> np .ndarray :
465
- # NB: A bunch of Interval tests fail if we use ._data
466
- return self .asi8
471
+ return self ._data
467
472
468
473
def _from_backing_data (self : _T , arr : np .ndarray ) -> _T :
469
474
# Note: we do not retain `freq`
470
- # error: Too many arguments for "NDArrayBackedExtensionArray"
471
- # error: Unexpected keyword argument " dtype" for "NDArrayBackedExtensionArray"
472
- return type ( self )( arr , dtype = self . dtype ) # type: ignore[call-arg]
475
+ return type ( self ). _simple_new ( # type: ignore[attr-defined]
476
+ arr , dtype = self . dtype
477
+ )
473
478
474
479
# ------------------------------------------------------------------
475
480
@@ -526,7 +531,7 @@ def __array__(self, dtype=None) -> np.ndarray:
526
531
# used for Timedelta/DatetimeArray, overwritten by PeriodArray
527
532
if is_object_dtype (dtype ):
528
533
return np .array (list (self ), dtype = object )
529
- return self ._data
534
+ return self ._ndarray
530
535
531
536
def __getitem__ (self , key ):
532
537
"""
@@ -536,7 +541,7 @@ def __getitem__(self, key):
536
541
537
542
if lib .is_integer (key ):
538
543
# fast-path
539
- result = self ._data [key ]
544
+ result = self ._ndarray [key ]
540
545
if self .ndim == 1 :
541
546
return self ._box_func (result )
542
547
return self ._simple_new (result , dtype = self .dtype )
@@ -557,7 +562,7 @@ def __getitem__(self, key):
557
562
key = check_array_indexer (self , key )
558
563
559
564
freq = self ._get_getitem_freq (key )
560
- result = self ._data [key ]
565
+ result = self ._ndarray [key ]
561
566
if lib .is_scalar (result ):
562
567
return self ._box_func (result )
563
568
return self ._simple_new (result , dtype = self .dtype , freq = freq )
@@ -612,7 +617,7 @@ def __setitem__(
612
617
613
618
value = self ._validate_setitem_value (value )
614
619
key = check_array_indexer (self , key )
615
- self ._data [key ] = value
620
+ self ._ndarray [key ] = value
616
621
self ._maybe_clear_freq ()
617
622
618
623
def _maybe_clear_freq (self ):
@@ -663,8 +668,8 @@ def astype(self, dtype, copy=True):
663
668
664
669
def view (self , dtype = None ):
665
670
if dtype is None or dtype is self .dtype :
666
- return type (self )(self ._data , dtype = self .dtype )
667
- return self ._data .view (dtype = dtype )
671
+ return type (self )(self ._ndarray , dtype = self .dtype )
672
+ return self ._ndarray .view (dtype = dtype )
668
673
669
674
# ------------------------------------------------------------------
670
675
# ExtensionArray Interface
@@ -705,7 +710,7 @@ def _from_factorized(cls, values, original):
705
710
return cls (values , dtype = original .dtype )
706
711
707
712
def _values_for_argsort (self ):
708
- return self ._data
713
+ return self ._ndarray
709
714
710
715
# ------------------------------------------------------------------
711
716
# Validation Methods
@@ -722,7 +727,7 @@ def _validate_fill_value(self, fill_value):
722
727
723
728
Returns
724
729
-------
725
- fill_value : np.int64
730
+ fill_value : np.int64, np.datetime64, or np.timedelta64
726
731
727
732
Raises
728
733
------
@@ -736,7 +741,8 @@ def _validate_fill_value(self, fill_value):
736
741
fill_value = self ._validate_scalar (fill_value , msg )
737
742
except TypeError as err :
738
743
raise ValueError (msg ) from err
739
- return self ._unbox (fill_value )
744
+ rv = self ._unbox (fill_value )
745
+ return self ._rebox_native (rv )
740
746
741
747
def _validate_shift_value (self , fill_value ):
742
748
# TODO(2.0): once this deprecation is enforced, use _validate_fill_value
@@ -951,9 +957,9 @@ def value_counts(self, dropna=False):
951
957
from pandas import Index , Series
952
958
953
959
if dropna :
954
- values = self [~ self .isna ()]._data
960
+ values = self [~ self .isna ()]._ndarray
955
961
else :
956
- values = self ._data
962
+ values = self ._ndarray
957
963
958
964
cls = type (self )
959
965
@@ -1044,9 +1050,9 @@ def fillna(self, value=None, method=None, limit=None):
1044
1050
else :
1045
1051
func = missing .backfill_1d
1046
1052
1047
- values = self ._data
1053
+ values = self ._ndarray
1048
1054
if not is_period_dtype (self .dtype ):
1049
- # For PeriodArray self._data is i8, which gets copied
1055
+ # For PeriodArray self._ndarray is i8, which gets copied
1050
1056
# by `func`. Otherwise we need to make a copy manually
1051
1057
# to avoid modifying `self` in-place.
1052
1058
values = values .copy ()
0 commit comments