Python 如何最好地使用pandas.DataFrame.pivot?
我正在尝试将数据帧从键行、值行转换为以键为列、值为单元格的表。例如: 输入带有键、值的数据帧:Python 如何最好地使用pandas.DataFrame.pivot?,python,pandas,Python,Pandas,我正在尝试将数据帧从键行、值行转换为以键为列、值为单元格的表。例如: 输入带有键、值的数据帧: >>>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
>>>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
我几乎可以通过pivot获得我想要的:
>>>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()
,但没有成功。您需要一个“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
另一种方法是:
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
您可以使用defaultdict在DataFrame构造函数中正常工作:
import collections
keys = ['TIME', 'VAL1', 'VAL2', 'VAL3', 'TIME', 'VAL1', 'VAL2', 'VAL3']
values = ["00:00:01",1,2,3,"00:00:02", 1,2,3]
d = collections.defaultdict(list)
for k, v in zip(keys, values):
d[k].append(v)
'''
d looks like this:
defaultdict(list,
{'TIME': ['00:00:01', '00:00:02'],
'VAL1': [1, 1],
'VAL2': [2, 2],
'VAL3': [3, 3]})'''
df = pd.DataFrame(d)
df
Out:
TIME VAL1 VAL2 VAL3
0 00:00:01 1 2 3
1 00:00:02 1 2 3
Nehal J Wani的替代方案,如果您无法访问这些列表:
df = pd.DataFrame([['TIME', 'VAL1', 'VAL2', 'VAL3',
'TIME', 'VAL1', 'VAL2', 'VAL3'],
["00:00:01",1,2,3,"00:00:02", 1,2,3]]).T
d = collections.defaultdict(list)
for k, v in zip(df[0], df[1]):
d[k].append(v)
嗯,我想我现在明白了这个枢轴函数应该如何工作了。pivot会在内存中创建数据的新副本吗?@Kyle:是的,它会。当VALx不是固定数量的行,而是在不同的时间段之间变化时,请使用它:
df['ID']=(df.index==“TIME”).cumsum()
有趣的想法。基本上是遍历键列的唯一值,选择这些值,并将这些列合并在一起?@Kyle是的,的确!问题是如何从原始数据帧中获取经过整形的数据帧,而不是如何直接从一些外部数据创建经过整形的数据帧。@BrenBarn OP的尝试,如pd.DataFrame.from\u items()
和pd.DataFrame.from\u records()
就是朝这个方向发展的,所以我认为这可能是一个解决方案。