我遇到了2个数据帧的情况:
test1 = pd.DataFrame({'id_A':['Ben', 'Julie', 'Jack', 'Jack'],
'id_B':['Julie', 'Ben', 'Nina', 'Julie']})
test2 = pd.DataFrame({'id_a':['Ben', 'Ben', 'Ben', 'Julie', 'Julie', 'Nina'],
'id_b':['Julie', 'Nina', 'Jack', 'Nina', 'Jack', 'Jack'],
'value':[1,1,0,0,1,0]})
>>> test1
id_A id_B
0 Ben Julie
1 Julie Ben
2 Jack Nina
3 Jack Julie
>>> test2
id_a id_b value
0 Ben Julie 1
1 Ben Nina 1
2 Ben Jack 0
3 Julie Nina 0
4 Julie Jack 1
5 Nina Jack 0
我想要做的是将test2
与test1
合并到id_A == id_a
和id_B == id_b
或,其中{{1} }和id_A == id_b
,产生以下数据框:
id_B == id_a
我的解决方案有效,但看起来很混乱,我想看看我是否会忽略一些更聪明的做事方式。它涉及将>>> final_df
id_A id_B value
0 Ben Julie 1
1 Julie Ben 1
2 Jack Nina 0
3 Jack Julie 1
与其自身连接,但将感兴趣的2列(test2
变为id_a
,反之亦然),然后从那里合并。
id_b
有谁知道更简洁的方法吗?我觉得我可能会忽略一些令人惊讶的令人愉快的做事方式。
感谢您的帮助!
答案 0 :(得分:2)
您可以尝试np.sort
test1.assign(key=pd.DataFrame(np.sort(test1.values,axis=1)).sum(1)).merge(test2.assign(key=pd.DataFrame(np.sort(test2[['id_a','id_b']].values,axis=1)).sum(1))).drop('key',1)
Out[188]:
id_A id_B id_a id_b value
0 Ben Julie Ben Julie 1
1 Julie Ben Ben Julie 1
2 Jack Nina Nina Jack 0
3 Jack Julie Julie Jack 1
答案 1 :(得分:2)
使用frozenset
test1.assign(
value=test1.apply(frozenset, 1).map({frozenset(a): b for *a, b in test2.values}))
id_A id_B value
0 Ben Julie 1
1 Julie Ben 1
2 Jack Nina 0
3 Jack Julie 1
不太可爱,更健壮。之后删除你需要的东西。
t1 = test1.assign(ref=list(map(frozenset, zip(test1.id_A, test1.id_B))))
t2 = test2.assign(ref=list(map(frozenset, zip(test2.id_a, test2.id_b))))
t1.merge(t2, on='ref')
id_A id_B ref id_a id_b value
0 Ben Julie (Julie, Ben) Ben Julie 1
1 Julie Ben (Julie, Ben) Ben Julie 1
2 Jack Nina (Jack, Nina) Nina Jack 0
3 Jack Julie (Jack, Julie) Julie Jack 1
答案 2 :(得分:1)
你可以做两个内连接,然后连接和去复制,如:
merge_1 = test1.merge(test2, left_on = ['id_A', 'id_B'], right_on= ['id_a', 'id_b'])
merge_2 = test1.merge(test2, left_on = ['id_A', 'id_B'], right_on= ['id_b', 'id_a'])
final_df = pd.concat([merge_1, merge_2]).drop_duplicates()
或者您可以执行外连接并手动计算条件:
final_df = test1.merge(test2, how='outer')
final_df = final_df[((final_df.id_A == final_df.id_a) &
(final_df.id_B == final_df.id_b)) |
((final_df.id_A == final_df.id_b) &
(final_df.id_B == final_df.id_a))]
或者您可以创建一个始终按照已知顺序的联接键:
test1['join_key'] = test1.apply(lambda row: tuple(sorted(row[['id_A', 'id_B']])), axis=1)
test2['join_key'] = test2.apply(lambda row: tuple(sorted(row[['id_a', 'id_b']])), axis=1)
final_df = test1.merge(test2, on='join_key').drop('join_key')