如何最好地使用pandas.DataFrame.pivot?

4

我将尝试将一个由键值对组成的数据框转换为以键作为列,值作为单元格的表格。例如:

带有键值对的输入数据框:

>>>df = pd.DataFrame([['TIME', 'VAL1', 'VAL2', 'VAL3', 
                       'TIME', 'VAL1', 'VAL2', 'VAL3'],
                      ["00:00:01",1,2,3,"00:00:02", 1,2,3]]).T

    0       1
0   TIME    00:00:01
1   VAL1    1
2   VAL2    2
3   VAL3    3
4   TIME    00:00:02
5   VAL1    1
6   VAL2    2
7   VAL3    3

我希望它看起来像这样:

TIME      VAL1 VAL2 VAL3
00:00:01  1    2    3
00:00:02  1    2    3

我几乎可以通过数据透视表得到我想要的结果:

>>>df.pivot(columns=0, values=1)
    TIME        VAL1    VAL2    VAL3
0   00:00:01    None    None    None
1   None        1       None    None
2   None        None    2       None
3   None        None    None    3
4   00:00:02    None    None    None
5   None        1       None    None
6   None        None    2       None
7   None        None    None    3

我可以合并行以得到我想要的结果:

>>> df.pivot(columns=0, values=1).ffill().drop_duplicates(subset='TIME',
                                                          keep='last').set_index('TIME')
TIME      VAL1 VAL2 VAL3
00:00:01  1    2    3
00:00:02  1    2    3

但这似乎是一种相当笨拙的方法,对于大数据集来说会浪费很多内存。有没有更简单的方法?

我试过查看 pd.DataFrame.from_items()pd.DataFrame.from_records(),但没有成功。

2个回答

3
您需要一个“ID”变量来指示哪些行应该在一起。在您期望的输出中,您暗示每个由4行组成的块应该成为单个行,但是pandas不会这样做,因为通常情况下,旋转应该能够将非连续的行分组在一起。新数据框中的每组要合并为单个行的行集必须具有某些共享值。
如果您的数据确实只是由四行组成的块,可以像这样创建ID变量:
df['ID'] = np.arange(len(df))//4

你可以看到,ID变量现在标记了哪些行应该被分组:
>>> df
      0         1  ID
0  TIME  00:00:01   0
1  VAL1         1   0
2  VAL2         2   0
3  VAL3         3   0
4  TIME  00:00:02   1
5  VAL1         1   1
6  VAL2         2   1
7  VAL3         3   1

然后将这个新列用作透视表的“索引”。
>>> df.pivot(index="ID", columns=0, values=1)
0       TIME VAL1 VAL2 VAL3
ID                         
0   00:00:01    1    2    3
1   00:00:02    1    2    3

嗯,我想我现在明白了这个枢轴函数应该如何工作。pivot会在内存中创建数据的新副本吗? - Kyle
@Kyle:是的,它确实可以。 - BrenBarn
当VALx不是一个固定的行数,而是在时间块之间变化时,请改用以下代码:df['ID'] = (df.index=="TIME").cumsum() - Zeugma

1
另一种做法:

In [65]: df
Out[65]: 
      0         1
0  TIME  00:00:01
1  VAL1         1
2  VAL2         2
3  VAL3         3
4  TIME  00:00:02
5  VAL1         1
6  VAL2         2
7  VAL3         3

In [66]: newdf = pd.concat([df[df[0] == x].reset_index()[1] for x in df[0].unique()], axis=1)

In [67]: newdf.columns = df[0].unique()

In [68]: newdf
Out[68]: 
       TIME VAL1 VAL2 VAL3
0  00:00:01    1    2    3
1  00:00:02    1    2    3

有趣的想法。基本上是通过迭代键列的唯一值,选择它们,并将列连接在一起吗? - Kyle
@Kyle 是的,确实! - Nehal J Wani

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