@@ -89,7 +89,6 @@ class Index(IndexOpsMixin, PandasObject):
89
89
_left_indexer = _algos .left_join_indexer_object
90
90
_inner_indexer = _algos .inner_join_indexer_object
91
91
_outer_indexer = _algos .outer_join_indexer_object
92
-
93
92
_box_scalars = False
94
93
95
94
_typ = 'index'
@@ -204,6 +203,17 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None, fastpath=False,
204
203
205
204
@classmethod
206
205
def _simple_new (cls , values , name = None , ** kwargs ):
206
+ """
207
+ we require the we have a dtype compat for the values
208
+ if we are passed a non-dtype compat, then coerce using the constructor
209
+
210
+ Must be careful not to recurse.
211
+ """
212
+ if not hasattr (values , 'dtype' ):
213
+ values = np .array (values ,copy = False )
214
+ if is_object_dtype (values ):
215
+ values = cls (values , name = name , ** kwargs ).values
216
+
207
217
result = object .__new__ (cls )
208
218
result ._data = values
209
219
result .name = name
@@ -341,15 +351,41 @@ def view(self, cls=None):
341
351
result ._id = self ._id
342
352
return result
343
353
344
- def _shallow_copy (self , values = None , ** kwargs ):
345
- """ create a new Index, don't copy the data, use the same object attributes
346
- with passed in attributes taking precedence """
354
+ def _shallow_copy (self , values = None , infer = False , ** kwargs ):
355
+ """
356
+ create a new Index, don't copy the data, use the same object attributes
357
+ with passed in attributes taking precedence
358
+
359
+ *this is an internal non-public method*
360
+
361
+ Parameters
362
+ ----------
363
+ values : the values to create the new Index, optional
364
+ infer : boolean, default False
365
+ if True, infer the new type of the passed values
366
+ kwargs : updates the default attributes for this Index
367
+ """
347
368
if values is None :
348
369
values = self .values
349
370
attributes = self ._get_attributes_dict ()
350
371
attributes .update (kwargs )
372
+
373
+ if infer :
374
+ attributes ['copy' ] = False
375
+ return Index (values , ** attributes )
376
+
351
377
return self .__class__ ._simple_new (values ,** attributes )
352
378
379
+ def _coerce_scalar_to_index (self , item ):
380
+ """
381
+ we need to coerce a scalar to a compat for our index type
382
+
383
+ Parameters
384
+ ----------
385
+ item : scalar item to coerce
386
+ """
387
+ return Index ([item ], dtype = self .dtype , ** self ._get_attributes_dict ())
388
+
353
389
def copy (self , names = None , name = None , dtype = None , deep = False ):
354
390
"""
355
391
Make a copy of this object. Name and dtype sets those attributes on
@@ -1132,7 +1168,9 @@ def append(self, other):
1132
1168
appended : Index
1133
1169
"""
1134
1170
to_concat , name = self ._ensure_compat_append (other )
1135
- return Index (np .concatenate (to_concat ), name = name )
1171
+ attribs = self ._get_attributes_dict ()
1172
+ attribs ['name' ] = name
1173
+ return self ._shallow_copy (np .concatenate (to_concat ), infer = True , ** attribs )
1136
1174
1137
1175
@staticmethod
1138
1176
def _ensure_compat_concat (indexes ):
@@ -1548,16 +1586,12 @@ def sym_diff(self, other, result_name=None):
1548
1586
other , result_name_update = self ._convert_can_do_setop (other )
1549
1587
if result_name is None :
1550
1588
result_name = result_name_update
1551
- the_diff_sorted = sorted (set ((self .difference (other )).union (other .difference (self ))))
1552
- if isinstance (self , MultiIndex ):
1553
- # multiindexes don't currently work well with _shallow_copy & can't be supplied a name
1554
- return Index (the_diff_sorted , ** self ._get_attributes_dict ())
1555
- else :
1556
- # convert list to Index and pull values out - required for subtypes such as PeriodIndex
1557
- diff_array = Index (the_diff_sorted ).values
1558
- return self ._shallow_copy (diff_array , name = result_name )
1559
-
1560
-
1589
+ the_diff = sorted (set ((self .difference (other )).union (other .difference (self ))))
1590
+ attribs = self ._get_attributes_dict ()
1591
+ attribs ['name' ] = result_name
1592
+ if 'freq' in attribs :
1593
+ attribs ['freq' ] = None
1594
+ return self ._shallow_copy (the_diff , infer = True , ** attribs )
1561
1595
1562
1596
def get_loc (self , key , method = None ):
1563
1597
"""
@@ -2535,7 +2569,8 @@ def delete(self, loc):
2535
2569
-------
2536
2570
new_index : Index
2537
2571
"""
2538
- return self ._shallow_copy (np .delete (self ._data , loc ))
2572
+ attribs = self ._get_attributes_dict ()
2573
+ return self ._shallow_copy (np .delete (self ._data , loc ), ** attribs )
2539
2574
2540
2575
def insert (self , loc , item ):
2541
2576
"""
@@ -2551,12 +2586,13 @@ def insert(self, loc, item):
2551
2586
-------
2552
2587
new_index : Index
2553
2588
"""
2554
- indexes = [self [:loc ],
2555
- Index ([item ]),
2556
- self [loc :]]
2557
-
2558
- return indexes [0 ].append (indexes [1 ]).append (indexes [2 ])
2589
+ _self = np .asarray (self )
2590
+ item = self ._coerce_scalar_to_index (item ).values
2559
2591
2592
+ idx = np .concatenate (
2593
+ (_self [:loc ], item , _self [loc :]))
2594
+ attribs = self ._get_attributes_dict ()
2595
+ return self ._shallow_copy (idx , infer = True , ** attribs )
2560
2596
2561
2597
def drop (self , labels , errors = 'raise' ):
2562
2598
"""
@@ -3687,7 +3723,7 @@ class MultiIndex(Index):
3687
3723
Level of sortedness (must be lexicographically sorted by that
3688
3724
level)
3689
3725
names : optional sequence of objects
3690
- Names for each of the index levels.
3726
+ Names for each of the index levels. (name is accepted for compat)
3691
3727
copy : boolean, default False
3692
3728
Copy the meta-data
3693
3729
verify_integrity : boolean, default True
@@ -3703,8 +3739,11 @@ class MultiIndex(Index):
3703
3739
rename = Index .set_names
3704
3740
3705
3741
def __new__ (cls , levels = None , labels = None , sortorder = None , names = None ,
3706
- copy = False , verify_integrity = True , _set_identity = True , ** kwargs ):
3742
+ copy = False , verify_integrity = True , _set_identity = True , name = None , ** kwargs ):
3707
3743
3744
+ # compat with Index
3745
+ if name is not None :
3746
+ names = name
3708
3747
if levels is None or labels is None :
3709
3748
raise TypeError ("Must pass both levels and labels" )
3710
3749
if len (levels ) != len (labels ):
@@ -4013,7 +4052,12 @@ def view(self, cls=None):
4013
4052
result ._id = self ._id
4014
4053
return result
4015
4054
4016
- _shallow_copy = view
4055
+ def _shallow_copy (self , values = None , infer = False , ** kwargs ):
4056
+ if values is not None :
4057
+ if 'name' in kwargs :
4058
+ kwargs ['names' ] = kwargs .pop ('name' ,None )
4059
+ return MultiIndex .from_tuples (values , ** kwargs )
4060
+ return self .view ()
4017
4061
4018
4062
@cache_readonly
4019
4063
def dtype (self ):
0 commit comments