@@ -824,10 +824,26 @@ def _validate_index_level(self, level):
824824 raise KeyError ('Level %s must be same as name (%s)'
825825 % (level , self .name ))
826826
827- def _get_level_number (self , level ):
827+ def _get_level_number (self , level , ignore_names = False ):
828+ if ignore_names and (not isinstance (level , int )):
829+ raise KeyError ('Level %s not found' % str (level ))
828830 self ._validate_index_level (level )
829831 return 0
830832
833+ def _get_level_numbers (self , levels , allow_mixed_names_and_numbers = False ):
834+ if levels is None :
835+ return list (range (self .nlevels ))
836+ elif isinstance (levels , (list , tuple , set )):
837+ if (not allow_mixed_names_and_numbers ) and (not all (lev in self .names for lev in levels )):
838+ if all (isinstance (lev , int ) for lev in levels ):
839+ return type (levels )(self ._get_level_number (level , ignore_names = True ) for level in levels )
840+ else :
841+ raise ValueError ("level should contain all level names or all level numbers, "
842+ "not a mixture of the two." )
843+ return type (levels )(self ._get_level_number (level ) for level in levels )
844+ else :
845+ return self ._get_level_number (levels )
846+
831847 @cache_readonly
832848 def inferred_type (self ):
833849 """ return a string of the type inferred from the values """
@@ -3161,28 +3177,30 @@ def _from_elements(values, labels=None, levels=None, names=None,
31613177 sortorder = None ):
31623178 return MultiIndex (levels , labels , names , sortorder = sortorder )
31633179
3164- def _get_level_number (self , level ):
3165- try :
3180+ def _get_level_number (self , level , ignore_names = False ):
3181+ if not ignore_names :
31663182 count = self .names .count (level )
31673183 if count > 1 :
31683184 raise ValueError ('The name %s occurs multiple times, use a '
31693185 '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 ))
3186+ try :
3187+ return self .names .index (level )
3188+ except ValueError :
3189+ pass
3190+ if not isinstance (level , int ):
3191+ raise KeyError ('Level %s not found' % str (level ))
3192+ elif level < 0 :
3193+ level += self .nlevels
3194+ if level < 0 :
3195+ orig_level = level - self .nlevels
3196+ raise IndexError (
3197+ 'Too many levels: Index has only %d levels, '
3198+ '%d is not a valid level number' % (self .nlevels , orig_level )
3199+ )
3200+ # Note: levels are zero-based
3201+ elif level >= self .nlevels :
3202+ raise IndexError ('Too many levels: Index has only %d levels, '
3203+ 'not %d' % (self .nlevels , level + 1 ))
31863204 return level
31873205
31883206 _tuples = None
@@ -4852,7 +4870,7 @@ def _trim_front(strings):
48524870
48534871
48544872def _sanitize_and_check (indexes ):
4855- kinds = list (set ([ type (index ) for index in indexes ] ))
4873+ kinds = list (set (type (index ) for index in indexes ))
48564874
48574875 if list in kinds :
48584876 if len (kinds ) > 1 :
@@ -4873,11 +4891,11 @@ def _get_consensus_names(indexes):
48734891
48744892 # find the non-none names, need to tupleify to make
48754893 # the set hashable, then reverse on return
4876- consensus_names = set ([
4894+ consensus_names = set (
48774895 tuple (i .names ) for i in indexes if all (n is not None for n in i .names )
4878- ] )
4896+ )
48794897 if len (consensus_names ) == 1 :
4880- return list (list ( consensus_names )[ 0 ] )
4898+ return list (consensus_names . pop () )
48814899 return [None ] * indexes [0 ].nlevels
48824900
48834901
0 commit comments