Python(pandas)筛选同时满足两个列表匹配条件的个体记录
问题分析
你现有代码的逻辑错误:pd.Series([*ListA,*ListB]).isin(x['medication']).all() 会要求用户必须使用过ListA和ListB合并后所有的药品(即同时用过A、Z、B、C四种)才会被保留,和你需要的「两个药品列表各至少使用过一种」的筛选规则完全不匹配,因此无法得到正确结果。
正确实现
方法1:分组filter直接判断
核心判断逻辑:对每个id的用药集合,分别检查和ListA、ListB是否存在交集,两个交集都非空才保留该id的所有记录。
import pandas as pd # 原始数据 df = pd.DataFrame({ 'id': [1,1,1,2,2,2,3,3,3], 'medication': ['A','B','A','Z','A','A','B','D','A'] }) ListA = ['A', 'Z'] ListB = ['B', 'C'] # 转集合提升交集判断效率 set_A = set(ListA) set_B = set(ListB) df_output = df.groupby('id').filter( lambda x: bool(set(x['medication']) & set_A) and bool(set(x['medication']) & set_B) )
运行后得到符合条件用户的全部用药记录:
id medication 0 1 A 1 1 B 2 1 A 6 3 B 7 3 D 8 3 A
方法2:transform标记(大数据量性能更优)
不用分组执行自定义函数,通过向量化运算标记符合条件的id再筛选,执行效率更高:
mask_a = df['medication'].isin(ListA).groupby(df['id']).transform('any') mask_b = df['medication'].isin(ListB).groupby(df['id']).transform('any') df_output = df[mask_a & mask_b]
按需调整输出格式
如果你需要的结果仅保留属于ListA/ListB范围内的药品、且去除重复行,可以在上述结果基础上追加过滤,就能得到你给出的示例输出:
df_output = df_output[df_output['medication'].isin(ListA + ListB)].drop_duplicates()
得到结果:
id medication 0 1 A 1 1 B 6 3 B 8 3 A
内容的提问来源于stack exchange,提问作者Economist_Ayahuasca
相关产品推荐
相关产品推荐

