DataFrame.index.levels 在削减数据帧后显示“额外”值

问题描述 投票:0回答:2

假设我有一个大型数据框

large
,其行上有一个多索引。我通过仅选择某些行来缩减此数据框并将结果分配给
small
。特别是,与
small
相比,
large
在其 MultiIndex 的第 0 级中具有更少的不同值。

然后,我想要

small
行上 MultiIndex 第 0 级中的不同值的列表,因此我调用
small.index.levels[0]
。结果很奇怪:它返回与
large.index.levels[0]
相同的东西,尽管值应该更少。

发生什么事了?

MWE:

import pandas as pd
import numpy as np

np.random.seed(0)

idx = pd.MultiIndex.from_product([['John', 'Josh', 'Alex'], list('abcde')], 
                                 names=['Person', 'Letter'])
large = pd.DataFrame(data=np.random.randn(15, 2), 
                     index=idx, 
                     columns=['one', 'two'])
small = large.loc[['Jo'==d[0:2] for d in large.index.get_level_values('Person')]]

print small.index.levels[0]
print large.index.levels[0]

输出:

Index([u'Alex', u'John', u'Josh'], dtype='object')
Index([u'Alex', u'John', u'Josh'], dtype='object')

预期输出:

Index([u'John', u'Josh'], dtype='object')
Index([u'Alex', u'John', u'Josh'], dtype='object')
python pandas multi-index
2个回答
1
投票

这样做效率更高。

In [43]: large[large.index.get_level_values('Person').to_series().str.startswith('Jo').values]
Out[43]: 
                    one       two
Person Letter                    
John   a       1.764052  0.400157
       b       0.978738  2.240893
       c       1.867558 -0.977278
       d       0.950088 -0.151357
       e      -0.103219  0.410599
Josh   a       0.144044  1.454274
       b       0.761038  0.121675
       c       0.443863  0.333674
       d       1.494079 -0.205158
       e       0.313068 -0.854096

回答你的问题。这是一个实现细节。使用

.get_level_values()
(而不是访问内部
.levels

如果你愿意,你可以这样做。

In [13]: small.index.get_level_values('Person').unique()
Out[13]: array(['John', 'Josh'], dtype=object)

In [14]: large.index.get_level_values('Person').unique()
Out[14]: array(['John', 'Josh', 'Alex'], dtype=object)

0
投票

我在遇到同样的问题后发现了这个问题,将其作为错误发布在pandas问题跟踪器上,并被告知这是预期的行为,因为pandas仅在切片时更新代码

MultiIndex
,而不是级别。您可以使用
MultiIndex.remove_unused_levels()
api 链接)删除不再位于切片中的级别。

所以在你的例子中:

small = large.loc[['Jo'==d[0:2] for d in large.index.get_level_values('Person')]]
small.index = small.index.remove_unused_levels()

print small.index.levels[0]
print large.index.levels[0]
© www.soinside.com 2019 - 2024. All rights reserved.