在多索引中输出标签

时间:2017-05-31 06:36:41

标签: python pandas

我正在阅读以下位置的多索引/高级索引

https://pandas.pydata.org/pandas-docs/stable/advanced.html

In [1]: arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
   ...:           ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
   ...: 

In [2]: tuples = list(zip(*arrays))

In [3]: tuples
Out[3]: 
[('bar', 'one'),
 ('bar', 'two'),
 ('baz', 'one'),
 ('baz', 'two'),
 ('foo', 'one'),
 ('foo', 'two'),
 ('qux', 'one'),
 ('qux', 'two')]

In [4]: index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

In [5]: index
Out[5]: 
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
           labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
           names=['first', 'second'])

我的问题是如何解释标签输出?以及如何根据给定的输入生成此输出。

2 个答案:

答案 0 :(得分:2)

级别是MultiIndex的所有可能唯一值。 labels映射此级别。

因此,第一级['bar', 'baz', 'foo', 'qux']由标签[0, 0, 1, 1, 2, 2, 3, 3]中定义的位置映射,输出为['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']。它适用于所有级别。

如果可以检查defined levels,则不会使用某些级别,但levels中会出现所有可能的值。

所以:

print (index[:4].values)
[('bar', 'one') ('bar', 'two') ('baz', 'one') ('baz', 'two')]

print (index[:4])
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
           names=['first', 'second'])

要删除,可以使用MultiIndex.remove_unused_levels版本0.20.0中的新功能

print (index[:4].remove_unused_levels())
MultiIndex(levels=[['bar', 'baz'], ['one', 'two']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
           names=['first', 'second'])

答案 1 :(得分:2)

labels是列表,其中每个子列表的长度必须相同。这是因为每个子列表的长度与索引本身的长度相同。每个子列表的每个成员都是相应levels子列表的位置。

因此pd.MultiIndex的第一个元素将由每个labels子列表的第一个元素决定。

第一个子列表的第一个元素是0,它对应于'bar'。第二个子列表的第一个元素是0,它对应于'one'。意味着索引的第一个元素是('bar', 'one')

当我们看到我们可以使用levels子列表对labels子列表进行切片时,这一点就更加明显了。

index.levels[0][index.labels[0]]

Index(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], dtype='object', name='first')

index.levels[1][index.labels[1]]

Index(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'], dtype='object', name='second')

我们可以将它们拼接在一起以创造我们期望的结果

list(zip(index.levels[0][index.labels[0]], index.levels[1][index.labels[1]]))

[('bar', 'one'),
 ('bar', 'two'),
 ('baz', 'one'),
 ('baz', 'two'),
 ('foo', 'one'),
 ('foo', 'two'),
 ('qux', 'one'),
 ('qux', 'two')]