转置多列 Pandas 数据帧

5

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

    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

我需要重新整理数据框,使其看起来像这样:
    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

我尝试使用pivot_table函数。
df.pivot_table(index=['m','r','s'], columns=['p'], values=['O','W','N']) 

但我无法得到我想要的。有人知道如何做吗?

2个回答

6
作为一个自认为很擅长pandas的人,`pivot_table` 和 `melt` 函数让我感到困惑。我更喜欢使用一个明确定义的唯一索引,并使用数据框本身的 `stack` 和 `unstack` 方法。
首先,我想问一下您是否真的需要像那样重复p列?我可以理解在展示数据时它的一定价值,但在我看来,pandas 不是真正以这种方式工作的。我们可以勉强塞进去,但让我们看看是否有更简单的解决方案能满足您的需求。
以下是我的做法:
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)

这将打印:

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

现在这些列是一个多重索引,您可以访问例如 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

同样地,您可以通过以下方式获取所有的 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

你可以使用 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

我看到你的做法了,但这是我编写的一个小脚本的最后一步,我需要输出结果看起来像我提到的那样。如果Pandas不是用于此操作的工具,您会推荐使用什么来操作数据框以获得所需的输出? - Daniel
太好了,这正是我需要的工作方式。我会仔细研究你使用的所有函数,以更好地了解它们的工作原理。 - Daniel
@Daniel stack -> melt; unstack -> pivot,但它们不以任何方式聚合数据,只操作行和列标签(索引)。 - Paul H

0
    b = open('ss2.csv', 'w')
    a = csv.writer(b)
    sk = ''
    with open ('df_col2.csv', 'r') as ann:
        for col in ann:
            an = col.lower().strip('\n').split(',')
            suk += an[0] + ','
    sk = sk[:-2]
    a.writerow([sk])

请在您的代码中包含解释,说明它的作用以及为什么它能回答问题。 - m13op22

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