我有一个DataFrame df1
,它是df
的一个切片。 df
是多索引的,形状为(8,)
。切片删除了df
的第二级。当我执行df1.shape
时,它会返回(4,)
- 一切都很好 - 但是当我执行df1.index.levels[0]
时,它会返回(4,)
。怎么会发生这种情况?
In [ ]:
arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),
np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
df = pd.DataFrame(np.random.randn(8,2), index=arrays)
df
Out [ ]:
0 1
bar one -0.447155 -0.323073
two 0.115899 -0.015561
baz one -0.272498 1.847073
two -0.399948 -0.264327
foo one 0.169687 -1.708543
two 1.154434 0.878936
qux one 0.535721 0.437186
two -1.203431 0.568412
In [ ]:
df1=df[df[1]>0]
Out [ ]:
0 1
baz one -0.272498 1.847073
foo two 1.154434 0.878936
qux one 0.535721 0.437186
two -1.203431 0.568412
现在是奇怪的一点
In [ ]:
df1=df[df[1]>0]
print(df1.index.levels[0], df1.index.levels[0].shape)
Out [ ]:
Index(['bar', 'baz', 'foo', 'qux'], dtype='object') (4,)
我发现这很奇怪,因为bar
中没有显示df1
。这背后的原因是什么?
我的猜测是复制/不复制,但我不明白为什么。
答案 0 :(得分:3)
根据docs:
注意MultiIndex的repr显示索引的所有已定义级别,即使它们实际未被使用也是如此。切片索引时,您可能会注意到这一点。 ...
这样做是为了避免重新计算级别,以使切片具有高性能。如果你想看到实际使用的水平......
使用仅使用的级别重建多索引
df1.index = pd.MultiIndex.from_tuples(df1.index)
答案 1 :(得分:2)
考虑两个指标:
In [59]: df.index
Out[59]:
MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]])
In [58]: df1.index
Out[58]:
MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']],
labels=[[1, 2, 3, 3], [0, 1, 0, 1]])
使用df1
构建df1 = df[df[1]>0]
时,Pandas可以构建df1.index
只是改变labels
。而且,如果它不改变levels
,那么
它不必重新编号labels
。这就是df1.index
包含bar
的原因
即使df1
未使用bar
。
您可以使用reset_index/set_index
:
In [63]: df1.reset_index().set_index(['level_0', 'level_1']).index
Out[63]:
MultiIndex(levels=[[u'baz', u'foo', u'qux'], [u'one', u'two']],
labels=[[0, 1, 2, 2], [0, 1, 0, 1]],
names=[u'level_0', u'level_1'])
- 或者使用Alexander's faster solution,df1.index = pd.MultiIndex.from_tuples(df1.index)
- 但是Pandas
默认情况下不会这样做可能是为了获得更好的性能。
答案 2 :(得分:1)
这是因为级别只是标签,它是决定该标签存在哪些标签的第二级值,例如在我的情况下:
In [2]:
arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),
np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
df = pd.DataFrame(np.random.randn(8,2), index=arrays)
df
Out[2]:
0 1
bar one 1.226303 0.017598
two 0.940893 1.491474
baz one 0.335430 1.178512
two -1.006346 -0.733090
foo one -0.765838 -0.494056
two -1.744994 -1.001641
qux one 0.177123 -0.969671
two 0.544314 -0.026114
In [3]:
df1=df[df[1]>0]
df1.index
Out[3]:
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1], [0, 1, 0]])
给出:
In [4]:
df1
Out[4]:
0 1
bar one 1.226303 0.017598
two 0.940893 1.491474
baz one 0.335430 1.178512
所以,如果你看一下索引:
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1], [0, 1, 0]])
值:labels=[[0, 0, 1], [0, 1, 0]
是存在的级别值的值,这就是您看到所有4个标签并且形状为4的原因