Pandas: 使用现有索引和列创建 MultiIndex / groupby headers

Pandas: Create MultiIndex / groupby using existing index and column headers

我正在尝试获取二维数据框并将其转换为 (more-or-less) one-dimensional 数据框,其中现有列用作第一级索引和列headers作为二级索引。

我一直在尝试 .melt().groupby().transpose().MultiIndex().pivot()...都没有任何运气 - 我认为主要是与它们需要以某种我无法理解的方式组合的事实有关。

设置:

import pandas as pd
from io import StringIO

csv = StringIO(u'''
AXIS    A       B       C       D
X       100     101     102     103 
Y       200     201     202     203
Z       300     301     302     303
''')

df = pd.read_csv(csv, delim_whitespace = True)

期望输出:

                Num
One     Two     
  X       A     100
  X       B     101
  X       C     102
  X       D     103
  Y       A     200
  Y       B     201
  Y       C     202
  Y       D     203
  Z       A     300
  Z       B     301
  Z       C     302
  Z       D     303

提前致谢。

使用,set_indexstack,和reset_index

df.set_index('AXIS').stack().reset_index()

输出:

   AXIS level_1    0
0     X       A  100
1     X       B  101
2     X       C  102
3     X       D  103
4     Y       A  200
5     Y       B  201
6     Y       C  202
7     Y       D  203
8     Z       A  300
9     Z       B  301
10    Z       C  302
11    Z       D  303

并且,您可以通过重命名列、重置索引等来做一些内务处理...

df.set_index('AXIS').stack().reset_index().rename(columns={'AXIS':'one','level_1':'two',0:'num'}).set_index(['one','two'])

输出:

         num
one two     
X   A    100
    B    101
    C    102
    D    103
Y   A    200
    B    201
    C    202
    D    203
Z   A    300
    B    301
    C    302
    D    303

正如您所怀疑的那样,诀窍在于组合正确的 id 和 value 变量

 pd.melt(df, id_vars=['AXIS'], value_vars=['A', 'B', 'C', 'D']).sort_values(['AXIS'])
#Using pd.melt to convert columns to rows.
pd.melt(df.rename(columns={'AXIS':'ONE'}),id_vars='ONE', var_name='TWO', value_name='Num').set_index(['ONE','TWO']).sort_index()
Out[28]: 
         Num
ONE TWO     
X   A    100
    B    101
    C    102
    D    103
Y   A    200
    B    201
    C    202
    D    203
Z   A    300
    B    301
    C    302
    D    303

我喜欢这个速度

i = df.AXIS.values
c = np.array(list('ABCD'))
v = np.column_stack([df[col].values for col in c])
idx = pd.MultiIndex.from_arrays(
    [i.repeat(c.size), np.tile(c, i.size)],
    names=['One', 'Two']
)
# Or this for brevity
# idx = pd.MultiIndex.from_product([i, c], names=['One', 'Two'])
pd.DataFrame(v.ravel(), idx, ['Num'])

         Num
One Two     
X   A    100
    B    101
    C    102
    D    103
Y   A    200
    B    201
    C    202
    D    203
Z   A    300
    B    301
    C    302
    D    303