为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

喵喵时光机 2022-09-20 16:46:18
我有一个像这样的df:frame = pd.DataFrame({'a' : ['a,b,c', 'a,c,f', 'b,d,f','a,z,c']})以及项目列表:letters = ['a','c']我的目标是从中获取至少包含 2 个元素的所有行frameletters我想出了这个解决方案:for i in letters:     subframe = frame[frame['a'].str.contains(i)]这给了我想要的东西,但就可伸缩性而言,它可能不是最好的解决方案。是否有任何“矢量化”解决方案?谢谢
查看完整描述

6 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

我会建立一个系列列表,然后应用一个矢量化: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


查看完整回答
反对 回复 2022-09-20
?
POPMUISE

TA贡献1765条经验 获得超5个赞

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

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'

)

//img1.sycdn.imooc.com//63297e130001ce9f08390589.jpg


查看完整回答
反对 回复 2022-09-20
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

这也解决了它:

frame[frame['a'].apply(lambda x: np.all([*map(lambda l: l in x, letters)]))]


查看完整回答
反对 回复 2022-09-20
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

您可以使用 :np.intersect1d


import pandas as pd

import numpy as np


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

letters = ['a','c']


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

print(frame[mask])


    a

0  a,b,c

1  a,c,f

3  a,z,c


查看完整回答
反对 回复 2022-09-20
?
RISEBY

TA贡献1856条经验 获得超5个赞

使用集:是次级集:


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

letters = ['a','c']


frame[frame['a'].apply(lambda x: set(letters).issubset(x))]


Out:


       a

0  a,b,c

1  a,c,f

3  a,z,c


查看完整回答
反对 回复 2022-09-20
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

IIUC 和布尔滤波器explode


这个想法是创建一个单一的系列,然后我们可以分组索引,使用累积总和来计算列表的真实发生次数


s = frame['a'].str.split(',').explode().isin(letters).groupby(level=0).cumsum()


print(s)


0    1.0

0    1.0

0    2.0

1    1.0

1    2.0

1    2.0

2    0.0

2    0.0

2    0.0

3    1.0

3    1.0

3    2.0

frame.loc[s[s.ge(2)].index.unique()]


out:


       a

0  a,b,c

1  a,c,f

3  a,z,c


查看完整回答
反对 回复 2022-09-20
  • 6 回答
  • 0 关注
  • 80 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号