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)