python - 如何检查一列的每个值是否正好映射到另一列中的一个值?

标签 python pandas performance dataframe

我有一个这样的数据框

import pandas as pd

df = pd.DataFrame({'A':list('bbcddee'), 'B': list('klmnnoi')})

   A  B
0  b  k
1  b  l
2  c  m
3  d  n
4  d  n
5  e  o
6  e  i
我想从 A 列创建一个字典和 B使用例如
dict(zip(df.A, df.B))
在此之前,我想检查 A 中的每个值是否仅映射到 B 中的一个值;如果不是,则应抛出错误;以上情况并非如此 b映射到 kle映射到 oi .
接近它的一种方法是:
df[df.groupby('A', sort=False)['B'].transform(lambda x: len(set(x))) > 1]
返回
   A  B
0  b  k
1  b  l
5  e  o
6  e  i
但是,这需要 lambda这可能会使它变慢。有没有人看到加快速度的选项?

最佳答案

您可以 groupbynunique获取“B”中有多少个唯一值属于“A”中的每个唯一值。

df.groupby('A').B.nunique()
#A
#b    2
#c    1
#d    1
#e    2
#Name: B, dtype: int64
因此,您可以检查其中是否有超过 1 个映射:
df.groupby('A').B.nunique().gt(1).any()
#True

以上在概念上与您提出的没有什么不同。但是,如果您能够使用已“优化”的内置 groupby 操作,而不是需要循环的慢速 lambda,则通常会获得重大的性能提升。我们可以看到,随着 DataFrame 变大,lambda 会变慢近 100 倍,这在开始需要几秒钟来计算时是一个大问题。
import perfplot
import pandas as pd
import numpy as np

def gb_lambda(df):
    return df.groupby('A')['B'].apply(lambda x: len(set(x))).gt(1)

def gb_nunique(df):
    return df.groupby('A').B.nunique().gt(1)

perfplot.show(
    setup=lambda n: pd.DataFrame({'A': np.random.randint(0, n//2, n), 
                                  'B': np.random.randint(0, n//2, n)}),
    kernels=[
        lambda df: gb_lambda(df),
        lambda df: gb_nunique(df),
    ],
    labels=['groupby with lambda', 'Groupby.nunique'],
    n_range=[2 ** k for k in range(2,18)],
    equality_check=np.allclose,  
    xlabel='~len(df)'
)
enter image description here

关于python - 如何检查一列的每个值是否正好映射到另一列中的一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62742322/

相关文章:

python - 将列表中找到的 ID 添加到 Pandas 数据框中的新列

python - 使用Python解析Json文件时出现关键错误

java - StringBuilder/StringBuffer 与 "+"运算符

python - 保留第一个非零元素,将所有其他元素设置为 0

python - 在功能 'error'/root/torch/install/share/lua/5.1/trepl/init.lua :389: in function 'require'

python - 无法使用opencv打开视频

python - matplotlib 两个 y 轴混合 z 顺序

python - 仅在 Pandas python 中索引和选择找到的列

python - 如果日期在给定范围内,则从每个组中删除行

Java 性能 - 最快的 'boolean' 会是什么?