基于多组对应条件过滤DataFrame列的问题及解决
问题描述
现有如下结构的DataFrame:
col1 col2 col3 col4 a a c c b a c c c a c c a b c c b b c c c b c c
同时有两个列表:
list1 = [['a', 'b'], ['a']] list2 = ['a', 'b']
过滤规则对应列表位置:
- 当
col2取值为'a'时,col1需为'a'或'b' - 当
col2取值为'b'时,col1需为'a'
尝试使用以下循环过滤时,得到空DataFrame:
for i, j in zip(list1, list2): df = df.loc[(df['col1'].isin(i)) & (df['col2'] == j)]
期望的过滤结果为:
col1 col2 col3 col4 a a c c b a c c a b c c
附数据生成代码:
import pandas as pd df = pd.DataFrame({ 'col1': ['a', 'b', 'c', 'a', 'b', 'c'], 'col2': ['a', 'a', 'a', 'b', 'b', 'b'], 'col3': ['c', 'c', 'c', 'c', 'c', 'c'], 'col4': ['c', 'c', 'c', 'c', 'c', 'c'], }) expected_output = pd.DataFrame({ 'col1': ['a', 'b', 'a'], 'col2': ['a', 'a', 'b'], 'col3': ['c', 'c', 'c'], 'col4': ['c', 'c', 'c'] }) list1 = [['a', 'b'], ['a']] list2 = ['a', 'b']
错误原因
原循环的问题在于每次迭代都会覆盖原始DataFrame:第一次过滤后,df只剩下col2='a'且col1为'a'/'b'的行;第二次迭代时,当前df中已经没有col2='b'的行,最终得到空DataFrame。
正确实现方法
方案一:构建复合逻辑掩码(推荐)
通过逻辑或(|)将所有条件组合,一次性过滤:
# 初始化掩码为全False mask = pd.Series(False, index=df.index) for col1_vals, col2_val in zip(list1, list2): # 逐个条件叠加逻辑或 mask |= (df['col1'].isin(col1_vals)) & (df['col2'] == col2_val) df_filtered = df[mask]
方案二:用字典映射规则(更直观)
先将过滤规则转化为字典,再逐行验证:
# 构建col2到允许col1值的映射字典 rule_dict = dict(zip(list2, list1)) # 过滤:判断每行col1是否在对应col2的允许列表中 df_filtered = df[df.apply(lambda row: row['col1'] in rule_dict[row['col2']], axis=1)]
方案三:循环收集子DataFrame再合并
每次循环将符合条件的行存入列表,最后合并:
filtered_dfs = [] for col1_vals, col2_val in zip(list1, list2): filtered_dfs.append(df.loc[(df['col1'].isin(col1_vals)) & (df['col2'] == col2_val)]) # 合并所有子DataFrame,重置索引 df_filtered = pd.concat(filtered_dfs, ignore_index=True)
以上三种方法均能得到符合预期的过滤结果。
内容的提问来源于stack exchange,提问作者zoro
相关产品推荐
相关产品推荐

