@@ -39,7 +39,6 @@ class DatetimeIndexOpsMixin(DatetimeLikeArrayMixin):
39
39
40
40
# override DatetimeLikeArrayMixin method
41
41
copy = Index .copy
42
- unique = Index .unique
43
42
44
43
# DatetimeLikeArrayMixin assumes subclasses are mutable, so these are
45
44
# properties there. They can be made into cache_readonly for Index
@@ -51,6 +50,30 @@ class DatetimeIndexOpsMixin(DatetimeLikeArrayMixin):
51
50
_resolution = cache_readonly (DatetimeLikeArrayMixin ._resolution .fget )
52
51
resolution = cache_readonly (DatetimeLikeArrayMixin .resolution .fget )
53
52
53
+ def unique (self , level = None ):
54
+ if level is not None :
55
+ self ._validate_index_level (level )
56
+
57
+ result = self ._eadata .unique ()
58
+
59
+ # Note: if `self` is already unique, then self.unique() should share
60
+ # a `freq` with self. If not already unique, then self.freq must be
61
+ # None, so again sharing freq is correct.
62
+ return self ._shallow_copy (result ._data )
63
+
64
+ @classmethod
65
+ def _create_comparison_method (cls , op ):
66
+ """
67
+ Create a comparison method that dispatches to ``cls.values``.
68
+ """
69
+ def wrapper (self , other ):
70
+ result = op (self ._eadata , maybe_unwrap_index (other ))
71
+ return result
72
+
73
+ wrapper .__doc__ = op .__doc__
74
+ wrapper .__name__ = '__{}__' .format (op .__name__ )
75
+ return wrapper
76
+
54
77
# A few methods that are shared
55
78
_maybe_mask_results = DatetimeLikeArrayMixin ._maybe_mask_results
56
79
@@ -106,7 +129,7 @@ def wrapper(left, right):
106
129
107
130
@Appender (DatetimeLikeArrayMixin ._evaluate_compare .__doc__ )
108
131
def _evaluate_compare (self , other , op ):
109
- result = DatetimeLikeArrayMixin . _evaluate_compare (self , other , op )
132
+ result = self . _eadata . _evaluate_compare (other , op )
110
133
if is_bool_dtype (result ):
111
134
return result
112
135
try :
@@ -406,7 +429,7 @@ def _add_datetimelike_methods(cls):
406
429
407
430
def __add__ (self , other ):
408
431
# dispatch to ExtensionArray implementation
409
- result = super ( cls , self ). __add__ (other )
432
+ result = self . _eadata . __add__ (maybe_unwrap_index ( other ) )
410
433
return wrap_arithmetic_op (self , other , result )
411
434
412
435
cls .__add__ = __add__
@@ -418,13 +441,13 @@ def __radd__(self, other):
418
441
419
442
def __sub__ (self , other ):
420
443
# dispatch to ExtensionArray implementation
421
- result = super ( cls , self ). __sub__ (other )
444
+ result = self . _eadata . __sub__ (maybe_unwrap_index ( other ) )
422
445
return wrap_arithmetic_op (self , other , result )
423
446
424
447
cls .__sub__ = __sub__
425
448
426
449
def __rsub__ (self , other ):
427
- result = super ( cls , self ). __rsub__ (other )
450
+ result = self . _eadata . __rsub__ (maybe_unwrap_index ( other ) )
428
451
return wrap_arithmetic_op (self , other , result )
429
452
430
453
cls .__rsub__ = __rsub__
@@ -548,9 +571,8 @@ def astype(self, dtype, copy=True):
548
571
549
572
@Appender (DatetimeLikeArrayMixin ._time_shift .__doc__ )
550
573
def _time_shift (self , periods , freq = None ):
551
- result = DatetimeLikeArrayMixin ._time_shift (self , periods , freq = freq )
552
- result .name = self .name
553
- return result
574
+ result = self ._eadata ._time_shift (periods , freq = freq )
575
+ return type (self )(result , name = self .name )
554
576
555
577
556
578
def wrap_arithmetic_op (self , other , result ):
@@ -589,7 +611,7 @@ def wrap_array_method(method, pin_name=False):
589
611
method
590
612
"""
591
613
def index_method (self , * args , ** kwargs ):
592
- result = method (self , * args , ** kwargs )
614
+ result = method (self . _eadata , * args , ** kwargs )
593
615
594
616
# Index.__new__ will choose the appropriate subclass to return
595
617
result = Index (result )
@@ -618,7 +640,7 @@ def wrap_field_accessor(prop):
618
640
fget = prop .fget
619
641
620
642
def f (self ):
621
- result = fget (self )
643
+ result = fget (self . _eadata )
622
644
if is_bool_dtype (result ):
623
645
# return numpy array b/c there is no BoolIndex
624
646
return result
@@ -629,6 +651,28 @@ def f(self):
629
651
return property (f )
630
652
631
653
654
+ def maybe_unwrap_index (obj ):
655
+ """
656
+ If operating against another Index object, we need to unwrap the underlying
657
+ data before deferring to the DatetimeArray/TimedeltaArray/PeriodArray
658
+ implementation, otherwise we will incorrectly return NotImplemented.
659
+
660
+ Parameters
661
+ ----------
662
+ obj : object
663
+
664
+ Returns
665
+ -------
666
+ unwrapped object
667
+ """
668
+ if isinstance (obj , ABCIndexClass ):
669
+ if isinstance (obj , DatetimeIndexOpsMixin ):
670
+ # i.e. PeriodIndex/DatetimeIndex/TimedeltaIndex
671
+ return obj ._eadata
672
+ return obj ._data
673
+ return obj
674
+
675
+
632
676
class DatetimelikeDelegateMixin (PandasDelegate ):
633
677
"""
634
678
Delegation mechanism, specific for Datetime, Timedelta, and Period types.
0 commit comments