我有这两个表:
T1
id x y
8 42 1.9
9 30 1.9
T2
id signal
8 55
8 56
8 59
9 57
9 58
9 60
目标是获得新表T3:
id x y s1 s2 s3
8 42 1.9 55 56 58
9 30 1.9 57 58 60
如果我执行此操作,那么它只会在没有转置的情况下执行合并:
pd.merge(T1, T2, on=['id'])
如何创建列s1
,s2
和s3
,每列对应一行(每id
行的行数始终固定且等于3)?
答案 0 :(得分:4)
<强>更新强>
正如@Jeff在他的评论中所写的那样@ ubuntu的解决方案应该比我的解决方案更快,更惯用:In [40]: T1.merge(
....: T2.pivot_table(index='id',
....: values='signal',
....: columns='s' + T2.groupby(['id'])['signal'].cumcount().astype(str))
....: .reset_index()
....: )
Out[40]:
id x y s0 s1 s2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
OLD回答:
你可以这样做:
In [209]: %paste
(t1.set_index('id')
.join(t2.groupby('id')['signal']
.apply(lambda x: x.tolist())
.apply(pd.Series))
.reset_index()
)
## -- End pasted text --
Out[209]:
id x y 0 1 2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
说明:
T2
组id
和&#34;收集&#34;所有相应的信号进入列表
In [211]: t2.groupby('id')['signal'].apply(lambda x: x.tolist())
Out[211]:
id
8 [55, 56, 59]
9 [57, 58, 60]
Name: signal, dtype: object
将列表展开到列
In [213]: t2.groupby('id')['signal'].apply(lambda x: x.tolist()).apply(pd.Series)
Out[213]:
0 1 2
id
8 55 56 59
9 57 58 60
最后按索引id
PS如果要重命名所有数字列,可以这样做(假设您将结果保存到rslt
DF):
In [224]: rslt.columns = [c if c in ['id','x','y'] else 's{}'.format(c) for c in rslt.columns.tolist()]
In [225]: rslt
Out[225]:
id x y s0 s1 s2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
答案 1 :(得分:2)
以下是我使用groupby
和unstack
的方式:
df = df1.merge(df2.groupby('id')['signal'].apply(lambda x: x.reset_index(drop=True)).unstack().reset_index())
df
Out[63]:
id x y 0 1 2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
如果我将它们分开:
df2t = df2.groupby('id')['signal'].apply(lambda x: x.reset_index(drop=True)).unstack().reset_index()
df2t
Out[59]:
id 0 1 2
0 8 55 56 59
1 9 57 58 60
df = df1.merge(df2t)
df
Out[61]:
id x y 0 1 2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
答案 2 :(得分:2)
另一种方法是使用groupby / cumcount / pivot:
import pandas as pd
T1 = pd.DataFrame({'id': [8, 9], 'x': [42, 30], 'y': [1.9, 1.9]})
T2 = pd.DataFrame({'id': [8, 8, 8, 9, 9, 9], 'signal': [55, 56, 59, 57, 58, 60]})
T2['col'] = 's' + T2.groupby(['id'])['signal'].cumcount().astype(str)
T2 = T2.pivot(index='id', columns='col', values='signal').reset_index()
result = pd.merge(T1, T2)
print(result)
产量
id x y s0 s1 s2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60
主要技巧是使用groupby/cumcount
将每组累积计数添加到T2:
In [81]: T2['col'] = 's' + T2.groupby(['id'])['signal'].cumcount().astype(str); T2
Out[81]:
id signal col
0 8 55 s0
1 8 56 s1
2 8 59 s2
3 9 57 s0
4 9 58 s1
5 9 60 s2
然后pivot
可用于将T2
重塑为(或至少接近)所需的格式:
In [82]: T2 = T2.pivot(index='id', columns='col', values='signal').reset_index(); T2
Out[82]:
col id s0 s1 s2
0 8 55 56 59
1 9 57 58 60
和result
可以通过合并来获得:
In [83]: pd.merge(T1, T2)
Out[83]:
id x y s0 s1 s2
0 8 42 1.9 55 56 59
1 9 30 1.9 57 58 60