@@ -123,6 +123,8 @@ class Index(IndexOpsMixin, PandasObject):
123123
124124 _engine_type = _index .ObjectEngine
125125
126+ ALL_LEVELS = - 1000
127+
126128 def __new__ (cls , data = None , dtype = None , copy = False , name = None , fastpath = False ,
127129 tupleize_cols = True , ** kwargs ):
128130
@@ -824,10 +826,26 @@ def _validate_index_level(self, level):
824826 raise KeyError ('Level %s must be same as name (%s)'
825827 % (level , self .name ))
826828
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 ))
828832 self ._validate_index_level (level )
829833 return 0
830834
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+
831849 @cache_readonly
832850 def inferred_type (self ):
833851 """ return a string of the type inferred from the values """
@@ -3161,28 +3179,30 @@ def _from_elements(values, labels=None, levels=None, names=None,
31613179 sortorder = None ):
31623180 return MultiIndex (levels , labels , names , sortorder = sortorder )
31633181
3164- def _get_level_number (self , level ):
3165- try :
3182+ def _get_level_number (self , level , ignore_names = False ):
3183+ if not ignore_names :
31663184 count = self .names .count (level )
31673185 if count > 1 :
31683186 raise ValueError ('The name %s occurs multiple times, use a '
31693187 '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 ))
31863206 return level
31873207
31883208 _tuples = None
@@ -4852,7 +4872,7 @@ def _trim_front(strings):
48524872
48534873
48544874def _sanitize_and_check (indexes ):
4855- kinds = list (set ([ type (index ) for index in indexes ] ))
4875+ kinds = list (set (type (index ) for index in indexes ))
48564876
48574877 if list in kinds :
48584878 if len (kinds ) > 1 :
@@ -4873,11 +4893,11 @@ def _get_consensus_names(indexes):
48734893
48744894 # find the non-none names, need to tupleify to make
48754895 # the set hashable, then reverse on return
4876- consensus_names = set ([
4896+ consensus_names = set (
48774897 tuple (i .names ) for i in indexes if all (n is not None for n in i .names )
4878- ] )
4898+ )
48794899 if len (consensus_names ) == 1 :
4880- return list (list ( consensus_names )[ 0 ] )
4900+ return list (consensus_names . pop () )
48814901 return [None ] * indexes [0 ].nlevels
48824902
48834903
0 commit comments