转置多列Pandas数据帧

Dan*_*nez 5 python pandas

我正在尝试重塑数据帧,但我无法得到我需要的结果.数据框如下所示:

    m   r   s   p   O       W       N         
    1   4   3   1   2.81    3.70    3.03  
    1   4   4   1   2.14    2.82    2.31  
    1   4   5   1   1.47    1.94    1.59  
    1   4   3   2   0.58    0.78    0.60  
    1   4   4   2   0.67    0.00    0.00
    1   4   5   2   1.03    2.45    1.68
    1   4   3   3   1.98    1.34    1.81
    1   4   4   3   0.00    0.04    0.15
    1   4   5   3   0.01    0.00    0.26
Run Code Online (Sandbox Code Playgroud)

我需要重塑数据帧,所以它看起来像这样:

    m   r   s   p   O       W       N      p    O       W       N     p  O      W       N
    1   4   3   1   2.81    3.70    3.03   2    0.58    0.78    0.60  3  1.98   1.34    1.81
    1   4   4   1   2.14    2.82    2.31   2    0.67    0.00    0.00  3 0.00    0.04    0.15
    1   4   5   1   1.47    1.94    1.59   2    1.03    2.45    1.68  3 0.01    0.00    0.26
Run Code Online (Sandbox Code Playgroud)

我试着使用这个pivot_table功能

df.pivot_table(index=['m','r','s'], columns=['p'], values=['O','W','N']) 
Run Code Online (Sandbox Code Playgroud)

但我无法得到我想要的东西.有谁知道如何做到这一点?

Pau*_*l H 6

作为一个喜欢自己与熊猫相当方便的人,这些pivot_tablemelt功能让我很困惑.我更愿意坚持使用一个明确定义和唯一索引,使用stackunstack数据框本身的方法.

首先,我会问你是否真的需要像这样重复p列?我可以在呈现数据时看到它的价值,但IMO熊猫并没有真正设置为这样工作.我们可以把它塞进去,但让我们看看一个更简单的解决方案是否能满足你的需求.

这就是我要做的事情:

from io import StringIO
import pandas

datatable = StringIO("""\
    m   r   s   p   O       W       N         
    1   4   3   1   2.81    3.70    3.03  
    1   4   4   1   2.14    2.82    2.31  
    1   4   5   1   1.47    1.94    1.59  
    1   4   3   2   0.58    0.78    0.60  
    1   4   4   2   0.67    0.00    0.00
    1   4   5   2   1.03    2.45    1.68
    1   4   3   3   1.98    1.34    1.81
    1   4   4   3   0.00    0.04    0.15
    1   4   5   3   0.01    0.00    0.26""")

df = (
    pandas.read_table(datatable, sep='\s+')
          .set_index(['m', 'r', 's', 'p'])
          .unstack(level='p')
)

df.columns = df.columns.swaplevel(0, 1)
df.sort(axis=1, inplace=True)

print(df)
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

p         1                 2                 3            
          O     W     N     O     W     N     O     W     N
m r s                                                      
1 4 3  2.81  3.70  3.03  0.58  0.78  0.60  1.98  1.34  1.81
    4  2.14  2.82  2.31  0.67  0.00  0.00  0.00  0.04  0.15
    5  1.47  1.94  1.59  1.03  2.45  1.68  0.01  0.00  0.26
Run Code Online (Sandbox Code Playgroud)

所以现在列是一个MultiIndex,你可以访问,例如,p = 2带有df[2]或的所有值df.xs(2, level='p', axis=1),这给了我:

          O     W     N
m r s                  
1 4 3  0.58  0.78  0.60
    4  0.67  0.00  0.00
    5  1.03  2.45  1.68
Run Code Online (Sandbox Code Playgroud)

类似地,您可以使用以下内容获取所有W列:( df.xs('W', level=1, axis=1) 我们说level=1),因为该列级别没有名称,因此我们使用其位置代替)

p         1     2     3
m r s                  
1 4 3  3.70  0.78  1.34
    4  2.82  0.00  0.04
    5  1.94  2.45  0.00
Run Code Online (Sandbox Code Playgroud)

您可以使用类似的方式查询列axis=0.

如果您确实需要p列中的值,只需手动添加它并重新索引列:

for p in df.columns.get_level_values('p').unique():
    df[p, 'p'] = p

cols = pandas.MultiIndex.from_product([[1,2,3], list('pOWN')])
df = df.reindex(columns=cols)
print(df)

       1                    2                    3                  
       p     O     W     N  p     O     W     N  p     O     W     N
m r s                                                               
1 4 3  1  2.81  3.70  3.03  2  0.58  0.78  0.60  3  1.98  1.34  1.81
    4  1  2.14  2.82  2.31  2  0.67  0.00  0.00  3  0.00  0.04  0.15
    5  1  1.47  1.94  1.59  2  1.03  2.45  1.68  3  0.01  0.00  0.26
Run Code Online (Sandbox Code Playgroud)