Pandas 一对一行合并,保持左边的结构?
Pandas one-to-one row merge, maintaining the structure on the left hand side?
与未解决的 SO 问题 (Can one perform a left join in pandas that selects only the first match on the right?) 类似的问题,但稍微复杂一些,并且没有明显的解决方法。我希望可能会有一些新的功能或灵感可用。
我有两个数据框,我想从上到下以一对一的方式合并,而不是笛卡尔方式。例如:
l1=['a','b','c','c']
l2=['001','002','003','004']
l3=['a','a','b','b','c','c','c','c']
l4=['006','007','008','009','010','011','012','013']
dfa=pd.DataFrame(list(zip(l1,l2)),columns=['A1','A2'])
dfb=pd.DataFrame(list(zip(l3,l4)),columns=['B1','B2'])
dfa
Out[968]:
A1 A2
0 a 001
1 b 002
2 c 003
3 c 004
dfb
Out[969]:
B1 B2
0 a 006
1 a 007
2 b 008
3 b 009
4 c 010
5 c 011
6 c 012
7 c 013
一旦我 'merge' 在 A1 和 B1 列上,我想要的结果是我最终只有 4 行,每个 A1 / B1 值的第一个实例相互连接,第二个实例每个 A1 / B1 值相互连接,依此类推:-
A1 A2 B2
0 a 001 006
1 b 002 008
2 c 003 010
3 c 004 011
我不能左合并然后 groupby 并采用 first() / head(1),因为 A1 中的 c 不是唯一的。出于同样的原因,我也不能在 dfb 的 B1 上 drop_duplicates() 。除此之外,除了一些复杂的使用循环之外,我没有想法。
有没有人有什么深刻的见解可以分享?
让我们尝试使用 groupby()
+cumcount()
创建一个 'key' 列来跟踪位置,然后在 A1、B1 和键上合并:
dfa['key']=dfa.groupby(['A1']).cumcount()
dfb['key']=dfb.groupby(['B1']).cumcount()
df=dfa.merge(dfb,left_on=['A1','key'],right_on=['B1','key']).drop(['B1','key'],1)
df
的输出:
A1 A2 B2
0 a 001 006
1 b 002 008
2 c 003 010
3 c 004 011
这是 assign
的版本。它真的和@Anurag Dabas 的版本一样工作
(dfa.assign(count=dfa.groupby('A1').transform('cumcount'))
.merge(dfb.assign(count=dfb.groupby('B1').transform('cumcount')),
left_on=('A1', 'count'), right_on=('B1', 'count'))
).drop(['count', 'B1'], axis=1)
与未解决的 SO 问题 (Can one perform a left join in pandas that selects only the first match on the right?) 类似的问题,但稍微复杂一些,并且没有明显的解决方法。我希望可能会有一些新的功能或灵感可用。
我有两个数据框,我想从上到下以一对一的方式合并,而不是笛卡尔方式。例如:
l1=['a','b','c','c']
l2=['001','002','003','004']
l3=['a','a','b','b','c','c','c','c']
l4=['006','007','008','009','010','011','012','013']
dfa=pd.DataFrame(list(zip(l1,l2)),columns=['A1','A2'])
dfb=pd.DataFrame(list(zip(l3,l4)),columns=['B1','B2'])
dfa
Out[968]:
A1 A2
0 a 001
1 b 002
2 c 003
3 c 004
dfb
Out[969]:
B1 B2
0 a 006
1 a 007
2 b 008
3 b 009
4 c 010
5 c 011
6 c 012
7 c 013
一旦我 'merge' 在 A1 和 B1 列上,我想要的结果是我最终只有 4 行,每个 A1 / B1 值的第一个实例相互连接,第二个实例每个 A1 / B1 值相互连接,依此类推:-
A1 A2 B2
0 a 001 006
1 b 002 008
2 c 003 010
3 c 004 011
我不能左合并然后 groupby 并采用 first() / head(1),因为 A1 中的 c 不是唯一的。出于同样的原因,我也不能在 dfb 的 B1 上 drop_duplicates() 。除此之外,除了一些复杂的使用循环之外,我没有想法。
有没有人有什么深刻的见解可以分享?
让我们尝试使用 groupby()
+cumcount()
创建一个 'key' 列来跟踪位置,然后在 A1、B1 和键上合并:
dfa['key']=dfa.groupby(['A1']).cumcount()
dfb['key']=dfb.groupby(['B1']).cumcount()
df=dfa.merge(dfb,left_on=['A1','key'],right_on=['B1','key']).drop(['B1','key'],1)
df
的输出:
A1 A2 B2
0 a 001 006
1 b 002 008
2 c 003 010
3 c 004 011
这是 assign
的版本。它真的和@Anurag Dabas 的版本一样工作
(dfa.assign(count=dfa.groupby('A1').transform('cumcount'))
.merge(dfb.assign(count=dfb.groupby('B1').transform('cumcount')),
left_on=('A1', 'count'), right_on=('B1', 'count'))
).drop(['count', 'B1'], axis=1)