检查 pandas 列是否包含列表中的所有元素

新手上路,请多包涵

我有一个这样的 df:

 frame = pd.DataFrame({'a' : ['a,b,c', 'a,c,f', 'b,d,f','a,z,c']})

以及项目清单:

 letters = ['a','c']

我的目标是从 frame 中获取至少包含 letters 中的 2 个元素的所有行

我想出了这个解决方案:

 for i in letters:
    subframe = frame[frame['a'].str.contains(i)]

这给了我想要的东西,但就可伸缩性而言,它可能不是最佳解决方案。有没有“矢量化”的解决方案?谢谢

原文由 AVal 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 741
2 个回答

我会构建一个系列列表,然后应用矢量化 np.all

 contains = [frame['a'].str.contains(i) for i in letters]
resul = frame[np.all(contains, axis=0)]

它按预期给出:

        a
0  a,b,c
1  a,c,f
3  a,z,c

原文由 Serge Ballesta 发布,翻译遵循 CC BY-SA 4.0 许可协议

一种方法是使用 str.split 将列值拆分为列表,并检查 set(letters) 是否是获得列表的 subset

 letters_s = set(letters)
frame[frame.a.str.split(',').map(letters_s.issubset)]

     a
0  a,b,c
1  a,c,f
3  a,z,c
​

基准:

 def serge(frame):
    contains = [frame['a'].str.contains(i) for i in letters]
    return frame[np.all(contains, axis=0)]

def yatu(frame):
    letters_s = set(letters)
    return frame[frame.a.str.split(',').map(letters_s.issubset)]

def austin(frame):
    mask =  frame.a.apply(lambda x: np.intersect1d(x.split(','), letters).size > 0)
    return frame[mask]

def datanovice(frame):
    s = frame['a'].str.split(',').explode().isin(letters).groupby(level=0).cumsum()
    return frame.loc[s[s.ge(2)].index.unique()]

perfplot.show(
    setup=lambda n: pd.concat([frame]*n, axis=0).reset_index(drop=True),

    kernels=[
        lambda df: serge(df),
        lambda df: yatu(df),
        lambda df: df[df['a'].apply(lambda x: np.all([*map(lambda l: l in x, letters)]))],
        lambda df: austin(df),
        lambda df: datanovice(df),
    ],

    labels=['serge', 'yatu', 'bruno','austin', 'datanovice'],
    n_range=[2**k for k in range(0, 18)],
    equality_check=lambda x, y: x.equals(y),
    xlabel='N'
)

在此处输入图像描述

原文由 yatu 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题