Python Pandas MultiIndex的子集适用于整个索引,但不适用于特定级别?

Python Pandas MultiIndex的子集适用于整个索引,但不适用于特定级别?,python,pandas,dataframe,multi-index,Python,Pandas,Dataframe,Multi Index,我在使用pd.MultiIndex时遇到了奇怪的行为,我正试图了解发生了什么。与其说是寻求解决方案,不如说是寻求解释 假设我有一个多索引数据帧: index0 = pd.Index(['a', 'b', 'c'], name='let') index1 = pd.Index(['foo', 'bar', 'baz'], name='word') x = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], index=[index0, index1])

我在使用
pd.MultiIndex
时遇到了奇怪的行为,我正试图了解发生了什么。与其说是寻求解决方案,不如说是寻求解释

假设我有一个多索引数据帧:

index0 = pd.Index(['a', 'b', 'c'], name='let')
index1 = pd.Index(['foo', 'bar', 'baz'], name='word')
x = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], index=[index0, index1])

display(x)

        0   1   2
let word            
a   foo 1   2   3
b   bar 4   5   6
c   baz 7   8   9
display(y.index)

MultiIndex([('a', 'foo'),
            ('c', 'baz')],
           names=['let', 'word'])
如果我用
df.loc
获取该数据帧的子集:

sub = ['a', 'c']
y = x.loc[sub]
display(y)

        0   1   2
let word            
a   foo 1   2   3
c   baz 7   8   9
到目前为止,一切顺利。现在,查看新数据帧的索引:

index0 = pd.Index(['a', 'b', 'c'], name='let')
index1 = pd.Index(['foo', 'bar', 'baz'], name='word')
x = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], index=[index0, index1])

display(x)

        0   1   2
let word            
a   foo 1   2   3
b   bar 4   5   6
c   baz 7   8   9
display(y.index)

MultiIndex([('a', 'foo'),
            ('c', 'baz')],
           names=['let', 'word'])
这也有道理。但如果我看一下子集数据帧索引的特定级别

display(y.index.levels[1])

Index(['bar', 'baz', 'foo'], dtype='object', name='word')
突然,我得到了原始完整数据帧的值,而不是所选的子集


为什么会发生这种情况?

我们需要为此添加一个特定的函数
删除未使用的级别
,因为它是类别类型数据

y.index.levels[0]
Index(['a', 'b', 'c'], dtype='object', name='let')

# after add
y.index=y.index.remove_unused_levels()
y.index.levels[0]
Index(['a', 'c'], dtype='object', name='let')

我们需要添加一个特定的函数
remove\u unused\u levels
,因为它是类别类型数据

y.index.levels[0]
Index(['a', 'b', 'c'], dtype='object', name='let')

# after add
y.index=y.index.remove_unused_levels()
y.index.levels[0]
Index(['a', 'c'], dtype='object', name='let')

我认为您混淆了
级别
获取级别值

y.index.get_level_values(1)
# Index(['foo', 'baz'], dtype='object', name='word')
y.index.levels
正如本在回答中提到的,只是所有可能的值(在截断之前)。让我们看另一个例子:

df = pd.DataFrame([[0]], 
                  index=pd.MultiIndex.from_product([[0,1],[0,1,2]]))
因此,
df
看起来像:

     0
0 0  0
  1  0
  2  0
1 0  0
  1  0
  2  0
现在,您认为使用
df.index.levels[1]
我们会得到什么?答案是:

Int64Index([0, 1, 2], dtype='int64')
它由级别中所有可能的值组成。鉴于,
df.index.get_level_值(1)
给出:

Int64Index([0, 1, 2, 0, 1, 2], dtype='int64')

我认为您混淆了
级别
获取级别值

y.index.get_level_values(1)
# Index(['foo', 'baz'], dtype='object', name='word')
y.index.levels
正如本在回答中提到的,只是所有可能的值(在截断之前)。让我们看另一个例子:

df = pd.DataFrame([[0]], 
                  index=pd.MultiIndex.from_product([[0,1],[0,1,2]]))
因此,
df
看起来像:

     0
0 0  0
  1  0
  2  0
1 0  0
  1  0
  2  0
现在,您认为使用
df.index.levels[1]
我们会得到什么?答案是:

Int64Index([0, 1, 2], dtype='int64')
它由级别中所有可能的值组成。鉴于,
df.index.get_level_值(1)
给出:

Int64Index([0, 1, 2, 0, 1, 2], dtype='int64')