使用第二个索引作为列将pandas多重索引系列转换为数据框

32

嗨,我有一个包含 2 层多级索引和一个列的DataFrame / Series。 我想要将第二层索引作为一列。 例如(代码取自多级索引文档):

import pandas as pd
import numpy as np

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
s = pd.DataFrame(np.random.randn(8), index=index, columns=["col"])

看起来像这样:

first  second
bar    one      -0.982656
       two      -0.078237
baz    one      -0.345640
       two      -0.160661
foo    one      -0.605568
       two      -0.140384
qux    one       1.434702
       two      -1.065408
dtype: float64

我希望的是拥有一个索引为[bar,baz,foo,qux]和列为[one,two]的DataFrame。

Translated text:

我希望的是拥有一个索引为[bar,baz,foo,qux]和列为[one,two]的DataFrame。

3个回答

55

你只需要unstack你的序列:

>>> s.unstack(level=1)
second       one       two
first                     
bar    -0.713374  0.556993
baz     0.523611  0.328348
foo     0.338351 -0.571854
qux     0.036694 -0.161852

2
我在这之后还做了 "s.columns = s.columns.droplevel(0)"。 - s5s

4
另一个强大的解决方案是使用 .reset_index.pivot:
levels= [['bar', 'baz'], ['one', 'two', 'three']]
index = pd.MultiIndex.from_product(levels, names=['first', 'second'])
series = pd.Series(np.random.randn(6), index)

df = series.reset_index()
# Shorthand notation instead of explicitly naming index, columns and values
df = df.pivot(*df.columns)

结果:

second       one     three       two
first                               
bar     1.047692  1.209063  0.891820
baz     0.083602 -0.303528 -1.385458

3

以下是使用数组重塑的解决方案 -

>>> idx = s.index.levels
>>> c = len(idx[1])
>>> pd.DataFrame(s.values.reshape(-1,c),index=idx[0].values, columns=idx[1].values)
          one       two
bar  2.225401  1.624866
baz  1.067359  0.349440
foo -0.468149 -0.352303
qux  1.215427  0.429146

如果您不关心索引顶部出现的名称-
>>> pd.DataFrame(s.values.reshape(-1,c), index=idx[0], columns=idx[1])
second       one       two
first                     
bar     2.225401  1.624866
baz     1.067359  0.349440
foo    -0.468149 -0.352303
qux     1.215427  0.429146

给定数据集大小的时间:

# @AChampion's solution
In [201]: %timeit s.unstack(level=1)
1000 loops, best of 3: 444 µs per loop

# Using array reshaping step-1
In [199]: %timeit s.index.levels
1000000 loops, best of 3: 214 ns per loop

# Using array reshaping step-2    
In [202]: %timeit pd.DataFrame(s.values.reshape(-1,2), index=idx[0], columns=idx[1])
10000 loops, best of 3: 47.3 µs per loop

2
这是我始终会考虑的一个选项。如果在所有级别上都不存在所有索引,则情况会变得棘手。换句话说,多重索引并不代表笛卡尔积。 - piRSquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接