@@ -123,6 +123,8 @@ class Index(IndexOpsMixin, PandasObject):
123
123
124
124
_engine_type = _index .ObjectEngine
125
125
126
+ ALL_LEVELS = - 1000
127
+
126
128
def __new__ (cls , data = None , dtype = None , copy = False , name = None , fastpath = False ,
127
129
tupleize_cols = True , ** kwargs ):
128
130
@@ -824,10 +826,26 @@ def _validate_index_level(self, level):
824
826
raise KeyError ('Level %s must be same as name (%s)'
825
827
% (level , self .name ))
826
828
827
- def _get_level_number (self , level ):
829
+ def _get_level_number (self , level , ignore_names = False ):
830
+ if ignore_names and (not isinstance (level , int )):
831
+ raise KeyError ('Level %s not found' % str (level ))
828
832
self ._validate_index_level (level )
829
833
return 0
830
834
835
+ def _get_level_numbers (self , levels , allow_mixed_names_and_numbers = False ):
836
+ if levels == self .ALL_LEVELS :
837
+ return list (range (self .nlevels ))
838
+ elif isinstance (levels , (list , tuple , set )):
839
+ if (not allow_mixed_names_and_numbers ) and (not all (lev in self .names for lev in levels )):
840
+ if all (isinstance (lev , int ) for lev in levels ):
841
+ return type (levels )(self ._get_level_number (level , ignore_names = True ) for level in levels )
842
+ else :
843
+ raise ValueError ("level should contain all level names or all level numbers, "
844
+ "not a mixture of the two." )
845
+ return type (levels )(self ._get_level_number (level ) for level in levels )
846
+ else :
847
+ return self ._get_level_number (levels )
848
+
831
849
@cache_readonly
832
850
def inferred_type (self ):
833
851
""" return a string of the type inferred from the values """
@@ -3161,28 +3179,30 @@ def _from_elements(values, labels=None, levels=None, names=None,
3161
3179
sortorder = None ):
3162
3180
return MultiIndex (levels , labels , names , sortorder = sortorder )
3163
3181
3164
- def _get_level_number (self , level ):
3165
- try :
3182
+ def _get_level_number (self , level , ignore_names = False ):
3183
+ if not ignore_names :
3166
3184
count = self .names .count (level )
3167
3185
if count > 1 :
3168
3186
raise ValueError ('The name %s occurs multiple times, use a '
3169
3187
'level number' % level )
3170
- level = self .names .index (level )
3171
- except ValueError :
3172
- if not isinstance (level , int ):
3173
- raise KeyError ('Level %s not found' % str (level ))
3174
- elif level < 0 :
3175
- level += self .nlevels
3176
- if level < 0 :
3177
- orig_level = level - self .nlevels
3178
- raise IndexError (
3179
- 'Too many levels: Index has only %d levels, '
3180
- '%d is not a valid level number' % (self .nlevels , orig_level )
3181
- )
3182
- # Note: levels are zero-based
3183
- elif level >= self .nlevels :
3184
- raise IndexError ('Too many levels: Index has only %d levels, '
3185
- 'not %d' % (self .nlevels , level + 1 ))
3188
+ try :
3189
+ return self .names .index (level )
3190
+ except ValueError :
3191
+ pass
3192
+ if not isinstance (level , int ):
3193
+ raise KeyError ('Level %s not found' % str (level ))
3194
+ elif level < 0 :
3195
+ level += self .nlevels
3196
+ if level < 0 :
3197
+ orig_level = level - self .nlevels
3198
+ raise IndexError (
3199
+ 'Too many levels: Index has only %d levels, '
3200
+ '%d is not a valid level number' % (self .nlevels , orig_level )
3201
+ )
3202
+ # Note: levels are zero-based
3203
+ elif level >= self .nlevels :
3204
+ raise IndexError ('Too many levels: Index has only %d levels, '
3205
+ 'not %d' % (self .nlevels , level + 1 ))
3186
3206
return level
3187
3207
3188
3208
_tuples = None
@@ -4852,7 +4872,7 @@ def _trim_front(strings):
4852
4872
4853
4873
4854
4874
def _sanitize_and_check (indexes ):
4855
- kinds = list (set ([ type (index ) for index in indexes ] ))
4875
+ kinds = list (set (type (index ) for index in indexes ))
4856
4876
4857
4877
if list in kinds :
4858
4878
if len (kinds ) > 1 :
@@ -4873,11 +4893,11 @@ def _get_consensus_names(indexes):
4873
4893
4874
4894
# find the non-none names, need to tupleify to make
4875
4895
# the set hashable, then reverse on return
4876
- consensus_names = set ([
4896
+ consensus_names = set (
4877
4897
tuple (i .names ) for i in indexes if all (n is not None for n in i .names )
4878
- ] )
4898
+ )
4879
4899
if len (consensus_names ) == 1 :
4880
- return list (list ( consensus_names )[ 0 ] )
4900
+ return list (consensus_names . pop () )
4881
4901
return [None ] * indexes [0 ].nlevels
4882
4902
4883
4903
0 commit comments