@@ -40,10 +40,17 @@ class Index(np.ndarray):
40
40
----
41
41
An Index instance can **only** contain hashable objects
42
42
"""
43
+ # Cython methods
43
44
_map_indices = lib .map_indices_object
44
45
_is_monotonic = lib .is_monotonic_object
45
46
_groupby = lib .groupby_object
46
47
_arrmap = lib .arrmap_object
48
+ _left_indexer = lib .left_join_indexer_object
49
+ _inner_indexer = lib .inner_join_indexer_object
50
+ _outer_indexer = lib .outer_join_indexer_object
51
+ _merge_indexer = lib .merge_indexer_object
52
+ _pad = lib .pad_object
53
+ _backfill = lib .backfill_object
47
54
48
55
name = None
49
56
def __new__ (cls , data , dtype = None , copy = False , name = None ):
@@ -100,7 +107,11 @@ def values(self):
100
107
101
108
@cache_readonly
102
109
def is_monotonic (self ):
103
- return self ._is_monotonic (self .values )
110
+ try :
111
+ # wrong buffer type raises ValueError
112
+ return self ._is_monotonic (self .values )
113
+ except TypeError :
114
+ return False
104
115
105
116
@property
106
117
def indexMap (self ):
@@ -331,12 +342,14 @@ def union(self, other):
331
342
if len (self ) == 0 :
332
343
return _ensure_index (other )
333
344
334
- if self .is_monotonic and other .is_monotonic :
335
- if other .dtype != np .object_ :
336
- other = Index (other , dtype = object )
345
+ if self .dtype != other .dtype :
346
+ this = self .astype ('O' )
347
+ other = other .astype ('O' )
348
+ return this .union (other )
337
349
350
+ if self .is_monotonic and other .is_monotonic :
338
351
try :
339
- result = lib . outer_join_indexer_object (self , other .values )[0 ]
352
+ result = self . _outer_indexer (self , other .values )[0 ]
340
353
except TypeError :
341
354
# incomparable objects
342
355
result = list (self .values )
@@ -385,17 +398,19 @@ def intersection(self, other):
385
398
if not hasattr (other , '__iter__' ):
386
399
raise Exception ('Input must be iterable!' )
387
400
401
+ other = _ensure_index (other )
402
+
388
403
if self .equals (other ):
389
404
return self
390
405
391
- other = _ensure_index ( other )
392
-
393
- if other . dtype != np . object_ :
394
- other = other . astype ( object )
406
+ if self . dtype != other . dtype :
407
+ this = self . astype ( 'O' )
408
+ other = other . astype ( 'O' )
409
+ return this . intersection ( other )
395
410
396
411
if self .is_monotonic and other .is_monotonic :
397
- return Index ( lib . inner_join_indexer_object (self ,
398
- other . values )[ 0 ] )
412
+ result = self . _inner_indexer (self , other . values )[ 0 ]
413
+ return self . _wrap_union_result ( other , result )
399
414
else :
400
415
indexer = self .get_indexer (other .values )
401
416
indexer = indexer .take ((indexer != - 1 ).nonzero ()[0 ])
@@ -484,20 +499,28 @@ def get_indexer(self, target, method=None):
484
499
target = _ensure_index (target )
485
500
486
501
if self .dtype != target .dtype :
502
+ this = Index (self , dtype = object )
487
503
target = Index (target , dtype = object )
504
+ return this .get_indexer (target , method = method )
505
+ # if self.dtype != target.dtype:
506
+ # target = Index(target, dtype=object)
488
507
489
508
if method == 'pad' :
490
- indexer = lib .pad_object (self , target , self .indexMap ,
491
- target .indexMap )
509
+ indexer = self ._pad (self , target , self .indexMap , target .indexMap )
492
510
elif method == 'backfill' :
493
- indexer = lib .backfill_object (self , target , self .indexMap ,
494
- target .indexMap )
511
+ indexer = self ._backfill (self , target , self .indexMap , target .indexMap )
495
512
elif method is None :
496
- indexer = lib . merge_indexer_object (target , self . indexMap )
513
+ indexer = self . _get_indexer_standard (target )
497
514
else :
498
515
raise ValueError ('unrecognized method: %s' % method )
499
516
return indexer
500
517
518
+ def _get_indexer_standard (self , other ):
519
+ if self .is_monotonic and other .is_monotonic :
520
+ return self ._left_indexer (other , self )
521
+ else :
522
+ return self ._merge_indexer (other , self .indexMap )
523
+
501
524
def groupby (self , to_groupby ):
502
525
return self ._groupby (self .values , to_groupby )
503
526
@@ -528,6 +551,11 @@ def reindex(self, target, method=None):
528
551
return target , indexer
529
552
530
553
def join (self , other , how = 'left' , return_indexers = False ):
554
+ if self .dtype != other .dtype :
555
+ this = self .astype ('O' )
556
+ other = other .astype ('O' )
557
+ return this .join (other , how = how , return_indexers = return_indexers )
558
+
531
559
if self .is_monotonic and other .is_monotonic :
532
560
return self ._join_monotonic (other , how = how ,
533
561
return_indexers = return_indexers )
@@ -559,25 +587,23 @@ def join(self, other, how='left', return_indexers=False):
559
587
def _join_monotonic (self , other , how = 'left' , return_indexers = False ):
560
588
this_vals = self .values
561
589
562
- if self .dtype != other .dtype :
563
- other = Index (other , dtype = object )
590
+ # if self.dtype != other.dtype:
591
+ # other = Index(other, dtype=object)
564
592
other_vals = other .values
565
593
566
594
if how == 'left' :
567
595
join_index = self
568
596
lidx = None
569
- ridx = lib . left_join_indexer_object (self , other )
597
+ ridx = self . _left_indexer (self , other )
570
598
elif how == 'right' :
571
599
join_index = other
572
- lidx = lib . left_join_indexer_object (other , self )
600
+ lidx = self . _left_indexer (other , self )
573
601
ridx = None
574
602
elif how == 'inner' :
575
- join_index , lidx , ridx = lib .inner_join_indexer_object (this_vals ,
576
- other_vals )
603
+ join_index , lidx , ridx = self ._inner_indexer (this_vals , other_vals )
577
604
join_index = self ._wrap_joined_index (join_index , other )
578
605
elif how == 'outer' :
579
- join_index , lidx , ridx = lib .outer_join_indexer_object (this_vals ,
580
- other_vals )
606
+ join_index , lidx , ridx = self ._outer_indexer (this_vals , other_vals )
581
607
join_index = self ._wrap_joined_index (join_index , other )
582
608
else : # pragma: no cover
583
609
raise Exception ('do not recognize join method %s' % how )
@@ -690,6 +716,12 @@ class Int64Index(Index):
690
716
_is_monotonic = lib .is_monotonic_int64
691
717
_groupby = lib .groupby_int64
692
718
_arrmap = lib .arrmap_int64
719
+ _left_indexer = lib .left_join_indexer_int64
720
+ _inner_indexer = lib .inner_join_indexer_int64
721
+ _outer_indexer = lib .outer_join_indexer_int64
722
+ _merge_indexer = lib .merge_indexer_int64
723
+ _pad = lib .pad_int64
724
+ _backfill = lib .backfill_int64
693
725
694
726
def __new__ (cls , data , dtype = None , copy = False , name = None ):
695
727
if not isinstance (data , np .ndarray ):
@@ -747,87 +779,9 @@ def equals(self, other):
747
779
748
780
return np .array_equal (self , other )
749
781
750
- def get_indexer (self , target , method = None ):
751
- target = _ensure_index (target )
752
-
753
- if self .dtype != target .dtype :
754
- this = Index (self , dtype = object )
755
- target = Index (target , dtype = object )
756
- return this .get_indexer (target , method = method )
757
-
758
- method = self ._get_method (method )
759
-
760
- if method == 'pad' :
761
- indexer = lib .pad_int64 (self , target , self .indexMap ,
762
- target .indexMap )
763
- elif method == 'backfill' :
764
- indexer = lib .backfill_int64 (self , target , self .indexMap ,
765
- target .indexMap )
766
- elif method is None :
767
- indexer = lib .merge_indexer_int64 (target , self .indexMap )
768
- else : # pragma: no cover
769
- raise ValueError ('unrecognized method: %s' % method )
770
- return indexer
771
- get_indexer .__doc__ = Index .get_indexer .__doc__
772
-
773
- def join (self , other , how = 'left' , return_indexers = False ):
774
- if not isinstance (other , Int64Index ):
775
- return Index .join (self .astype (object ), other , how = how ,
776
- return_indexers = return_indexers )
777
-
778
- if self .is_monotonic and other .is_monotonic :
779
- return self ._join_monotonic (other , how = how ,
780
- return_indexers = return_indexers )
781
- else :
782
- return Index .join (self , other , how = how ,
783
- return_indexers = return_indexers )
784
-
785
- def _join_monotonic (self , other , how = 'left' , return_indexers = False ):
786
- if how == 'left' :
787
- join_index = self
788
- lidx = None
789
- ridx = lib .left_join_indexer_int64 (self , other )
790
- elif how == 'right' :
791
- join_index = other
792
- lidx = lib .left_join_indexer_int64 (other , self )
793
- ridx = None
794
- elif how == 'inner' :
795
- join_index , lidx , ridx = lib .inner_join_indexer_int64 (self , other )
796
- join_index = Int64Index (join_index )
797
- elif how == 'outer' :
798
- join_index , lidx , ridx = lib .outer_join_indexer_int64 (self , other )
799
- join_index = Int64Index (join_index )
800
- else : # pragma: no cover
801
- raise Exception ('do not recognize join method %s' % how )
802
-
803
- if return_indexers :
804
- return join_index , lidx , ridx
805
- else :
806
- return join_index
807
-
808
- def intersection (self , other ):
809
- if not isinstance (other , Int64Index ):
810
- return Index .intersection (self .astype (object ), other )
811
-
812
- if self .is_monotonic and other .is_monotonic :
813
- result = lib .inner_join_indexer_int64 (self , other )[0 ]
814
- else :
815
- indexer = self .get_indexer (other )
816
- indexer = indexer .take ((indexer != - 1 ).nonzero ()[0 ])
817
- return self .take (indexer )
818
- return Int64Index (result )
819
- intersection .__doc__ = Index .intersection .__doc__
820
-
821
- def union (self , other ):
822
- if not isinstance (other , Int64Index ):
823
- return Index .union (self .astype (object ), other )
824
-
825
- if self .is_monotonic and other .is_monotonic :
826
- result = lib .outer_join_indexer_int64 (self , other )[0 ]
827
- else :
828
- result = np .unique (np .concatenate ((self , other )))
829
- return Int64Index (result )
830
- union .__doc__ = Index .union .__doc__
782
+ def _wrap_joined_index (self , joined , other ):
783
+ name = self .name if self .name == other .name else None
784
+ return Int64Index (joined , name = name )
831
785
832
786
class DateIndex (Index ):
833
787
pass
@@ -1321,14 +1275,13 @@ def get_indexer(self, target, method=None):
1321
1275
self_index = self .get_tuple_index ()
1322
1276
1323
1277
if method == 'pad' :
1324
- indexer = lib . pad_object (self_index , target_index ,
1325
- self_index . indexMap , target .indexMap )
1278
+ indexer = self . _pad (self_index , target_index , self_index . indexMap ,
1279
+ target .indexMap )
1326
1280
elif method == 'backfill' :
1327
- indexer = lib . backfill_object (self_index , target_index ,
1328
- self_index . indexMap , target .indexMap )
1281
+ indexer = self . _backfill (self_index , target_index , self_index . indexMap ,
1282
+ target .indexMap )
1329
1283
else :
1330
- indexer = lib .merge_indexer_object (target_index ,
1331
- self_index .indexMap )
1284
+ indexer = self ._merge_indexer (target_index , self_index .indexMap )
1332
1285
1333
1286
return indexer
1334
1287
0 commit comments