Python Pandas动态列与对应值过滤DataFrame报错求助
动态列过滤Pandas DataFrame的掩码问题
想通过字典里的多列条件动态过滤Pandas DataFrame,之前用字符串拼接生成过滤条件,结果返回的是字符串而非布尔掩码,导致KeyError。原代码及报错如下:
import pandas as pd # Create a list of dictionaries with the data for each row data = [{'col1': 1, 'col2': 'a', 'col3': True, 'col4': 1.0}, {'col1': 2, 'col2': 'b', 'col3': False, 'col4': 2.0}, {'col1': 1, 'col2': 'c', 'col3': True, 'col4': 3.0}, {'col1': 2, 'col2': 'd', 'col3': False, 'col4': 4.0}, {'col1': 1, 'col2': 'e', 'col3': True, 'col4': 5.0}] df = pd.DataFrame(data) filter_dict = {'col1': 1, 'col3': True,} def create_filter_query_for_df(filter_dict): query = "" for i, (column, values) in enumerate(filter_dict.items()): if i > 0: query += " & " if isinstance(values,float) or isinstance(values,int): query += f"(data['{column}'] == {values})" else: query += f"(data['{column}'] == '{values}')" return query df[create_filter_query_for_df(filter_dict)]
执行后报错:
KeyError: "(data['col1'] == 1) & (data['col3'] == True)"
解决方案
方案1:直接生成布尔掩码(推荐)
跳过字符串拼接,直接遍历条件生成布尔Series并叠加,得到符合要求的过滤掩码:
import pandas as pd data = [{'col1': 1, 'col2': 'a', 'col3': True, 'col4': 1.0}, {'col1': 2, 'col2': 'b', 'col3': False, 'col4': 2.0}, {'col1': 1, 'col2': 'c', 'col3': True, 'col4': 3.0}, {'col1': 2, 'col2': 'd', 'col3': False, 'col4': 4.0}, {'col1': 1, 'col2': 'e', 'col3': True, 'col4': 5.0}] df = pd.DataFrame(data) filter_dict = {'col1': 1, 'col3': True} def create_filter_mask(df, filter_dict): # 初始化全True的掩码 mask = pd.Series([True] * len(df)) for col, val in filter_dict.items(): # 逐个叠加条件 mask &= (df[col] == val) return mask filtered_df = df[create_filter_mask(df, filter_dict)] print(filtered_df)
方案2:使用pandas的query方法
若偏好字符串形式的查询语句,可利用df.query()方法,调整字符串格式适配其语法:
def create_query_string(filter_dict): conditions = [] for col, val in filter_dict.items(): if isinstance(val, str): # 字符串值需加引号,避免语法错误 conditions.append(f"{col} == '{val}'") elif isinstance(val, (int, float, bool)): # 数字、布尔值直接拼接 conditions.append(f"{col} == {val}") return " & ".join(conditions) query_str = create_query_string(filter_dict) filtered_df = df.query(query_str) print(filtered_df)
方案3:使用eval(不推荐)
如果一定要基于原字符串形式实现,可通过eval()将字符串转为布尔掩码,但注意:eval存在安全风险,若filter_dict来自不可信输入,禁止使用:
def create_filter_query_for_df(filter_dict): query = [] for column, values in filter_dict.items(): if isinstance(values, (float, int, bool)): query.append(f"(df['{column}'] == {values})") else: query.append(f"(df['{column}'] == '{values}')") return " & ".join(query) mask_str = create_filter_query_for_df(filter_dict) mask = eval(mask_str) filtered_df = df[mask] print(filtered_df)
内容的提问来源于stack exchange,提问作者Dubblej
相关产品推荐
相关产品推荐

