首页 > 解决方案 > pandas 如何找到一对一的相关值?

问题描述

我有df一对 id 并且我尝试过滤那些具有唯一一对一关系的对,以便没有任何left_id值具有多个对应right_id的值,同时,分别没有任何right_id值具有多个的对应值left_id

很简单,但我卡住了...

让我们生成一些示例数据进行说明:

np.random.seed(0)
df = pd.DataFrame(data = np.random.randint(0,1000,(1000000,2)),
                  index = np.arange(1000000), 
                  columns = ['left_id', 'right_id'])

像那样:

  left_id right_id
0  684   559
1  629   192
2  835   763
3  707   359
4  9     723

删除重复项:

单程:

len(df.drop_duplicates('left_id', keep=False).drop_duplicates('right_id', keep=False))

637

另一种方式:

len(df.drop_duplicates('right_id', keep=False).drop_duplicates('left_id', keep=False))

633

所以相同操作的结果并不一致,所以我认为这种方法是错误的。

如何使它正确?

标签: pythonpandas

解决方案


编辑:清晰度

我可以可靠地重新创建这个“问题”,我有预感会有一些重叠:

import pandas as pd

df = pd.DataFrame({"left" : [1, 2, 3, 4, 5, 7, 7, 9, 0, 1],                                                        
                   "right": [11, 12, 13, 14, 15, 15, 15, 17, 10, 20]}) 

像这样 :

 df.drop_duplicates("right", keep=False).drop_duplicates("left",keep=False)

    left  right
1     2     12
2     3     13
3     4     14
7     9     17
8     0     10

df.drop_duplicates("left", keep=False).drop_duplicates("right",keep=False)

    left  right
1     2     12
2     3     13
3     4     14
4     5     15
7     9     17
8     0     10

简而言之,如果一列中的任何删除使先前重复的值在另一列中成为唯一的;输出不会是对称的。

如果您尝试以下操作,则重复但没有重叠:

df2 = pd.DataFrame({"left" : [1, 2, 3, 4, 5, 5],
                    "right": [10, 10, 20 ,30, 40, 50]})

您会看到输出是相同的,您应该将重复项分开并将它们连接回来,这将确保保留每个真正唯一的值,并且您可以决定丢弃哪些值:

left = df["left"].drop_duplicates(keep=False)
right  = df["right"].drop_duplicates(keep=False)

one_to_one = pd.concat((left, right), axis=1)

one_to_one = one_to_one.dropna()

这种行为应该是您所期望的,只是要注意NaNfloat类型转换为列。


推荐阅读