仅允许Pandas DataFrame中两列之间的一对一映射

2 投票
1 回答
2610 浏览
提问于 2025-04-18 06:53

我有一个包含两列的数据表 df,每一行都是独特的。在一列中的一个元素可以对应到另一列中的一个或多个元素。我想要把那些元素过滤掉。最终的数据表中,一列中的一个元素只能对应到另一列中的一个独特元素。

我现在的做法是先按一列分组,然后统计重复的数量,再把数量超过1的行去掉。然后对另一列再做一次。我在想有没有更好、更简单的方法。

谢谢


补充1:我刚意识到我的解决方案是错误的,去掉A列中多重映射的元素会减少B列中的映射数量,看看下面这个例子:

A B

1 4

1 3

2 4

1对应3和4,所以前两行应该被去掉,而4又对应1和2。最终的表格应该是空的。然而,我的解决方案会保留最后一行。

有没有人能给我一个快速简单的解决方案?谢谢

1 个回答

2

好吧,你可以这样做:

>>> df

   A  B
0  1  4
1  1  3
2  2  4
3  3  5

你只想保留一行数据,前提是没有其他行的'A'列有值为'A',而且没有其他行的'B'列有值为'B'。在这个例子中,只有第三行符合这些条件:

>>> Aone = df.groupby('A').filter(lambda x: len(x) == 1)
>>> Bone = df.groupby('B').filter(lambda x: len(x) == 1)
>>> Aone.merge(Bone,on=['A','B'],how='inner')

    A  B
 0  3  5

解释:

>>> Aone = df.groupby('A').filter(lambda x: len(x) == 1)
>>> Aone

   A  B
2  2  4
3  3  5

上面的代码是根据'A'列的值来筛选可能允许的行。

>>> Bone = df.groupby('B').filter(lambda x: len(x) == 1)
>>> Bone

   A  B
1  1  3
3  3  5

上面的代码是根据'B'列的值来筛选可能允许的行。然后把这两部分的交集合并在一起,就得到了同时满足两个条件的行:

>>> Aone.merge(Bone,on=['A','B'],how='inner')

注意,你也可以用 groupby/transform 做类似的事情。不过,transform的速度比较慢,所以我没有把它作为替代方案。

撰写回答