假设我有以下DataFrame,其中每一行代表特定用户在特定时间执行的事件:
In [1]: df
Out[1]:
time event
user
a 1 x
a 2 y
a 3 z
b 1 x
b 2 x
b 3 z
b 4 z
c 1 y
c 2 y
c 3 z
d 1 z
我想重塑它,使其具有以下结构:
In [2]: dfm
Out[2]:
x y z
user
a 1 2 3
b 1 NaN 3
b 1 NaN 4
b 2 NaN 3
b 2 NaN 4
c NaN 1 3
c NaN 2 3
d NaN NaN 1
我目前通过首先为每个事件创建一个DataFrame来获得此结果:
In [3]: dfs = [d[['time']].rename(columns={'time': k}) for k, d in df.groupby('event')]
In [4]: dfs
Out[4]:
[ x
user
a 1
b 1
b 2, y
user
a 2
c 1
c 2, z
user
a 3
b 3
b 4
c 3
d 1]
然后多次调用pd.merge
:
In [5]: dfm = dfs[0]
In [5]: for d in dfs[1:]:
...: dfm = pd.merge(dfm, d, left_index=True, right_index=True, how='outer')
这很好用,但我想知道是否有更好的方法。这不是大熊猫第一次以一些漂亮的功能让我感到惊讶!我尝试了pd.concat(dfs, axis=1)
,但是产生了以下错误(仅显示了最后一行):
ValueError: Shape of passed values is (1, 5), indices imply (1, 4)
我也查看了pd.pivot_table
,但每个用户生成一行并平均时间戳。也许我忽略了一些东西。非常感谢任何帮助!
答案 0 :(得分:1)
以下是问题中讨论的解决方案
import pandas as pd
from StringIO import StringIO
data = \
'user,time,event\n\
a,1,x\n\
a,2,y\n\
a,3,z\n\
b,1,x\n\
b,2,x\n\
b,3,z\n\
b,4,z\n\
c,1,y\n\
c,2,y\n\
c,3,z\n\
d,1,z\n'
df = pd.read_csv(StringIO(data), index_col='user')
dfs = [d[['time']].rename(columns={'time': k}) for k, d in df.groupby('event')]
dfm = dfs[0]
for d in dfs[1:]:
dfm = pd.merge(dfm, d, left_index=True, right_index=True, how='outer')