pandas levels在解析数据框后显示“额外”值

ep6jt1vc  于 2023-09-29  发布在  其他
关注(0)|答案(2)|浏览(82)

假设我有一个大型 Dataframe large,它在行上有一个MultiIndex。我通过只选择一些行并将结果分配给small来帕雷这个 Dataframe 。特别是,small在其MultiIndex的第0级中的行上的不同值比large少。
然后,我需要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')
yhuiod9q

yhuiod9q1#

这样做更有效率。

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)
flseospp

flseospp2#

我在遇到同样的问题posted it as a bug on the pandas issues tracker后发现了这个问题,并被告知这是预期的行为,因为pandas在切片MultiIndex时只更新代码,而不是级别。您可以使用MultiIndex.remove_unused_levels()api link)删除切片中不再存在的级别。
在你的例子中:

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])

相关问题