如何避免Pandas AttributeError?适配DataFrame缺失列的动态条件
问题描述
我想创建一组可根据用户输入选择性评估的条件,但DataFrame的列不固定,也不会用到所有条件。比如针对支出信息预设了4列的条件,但用户只提供3列数据,这种情况下怎么存储并调用这些数据条件才不会报错?
预设条件对应的列:Date、Amount、Category、Year
用户提供的数据如下:
| Date | Amount | Category |
|---|---|---|
| 11-01-2022 | 190 | bill |
| 11-01-2022 | 50 | grocery |
| 11-01-2022 | 55 | shopping |
| 12-01-2022 | 10 | grocery |
| 12-01-2022 | 80 | bill |
| 12-01-2022 | 90 | grocery |
直接写条件会触发AttributeError,示例代码:
import pandas as pd df = pd.DataFrame( { 'Date' : ['11-01-2022', '11-01-2022', '11-01-2022', '12-01-2022', '12-01-2022', '12-01-2022'], 'Amount' : [190, 50, 55, 10, 80, 90], 'Category' : ['bill', 'grocery', 'shopping', 'grocery', 'bill', 'grocery'] } ) conditions = { 'december_amount_under_20' : (df.Date== 'Dec') & (df.Amount > 20), # 原示例Date判断不匹配数据格式,仅作报错演示 'year_2022' : df.Year == 2022 # 触发AttributeError }
解决方案
核心思路是延迟条件计算,别一开始就直接用DataFrame列生成布尔数组,而是把条件定义成可动态检查列的逻辑,避免直接访问不存在的列。
方法一:封装条件为函数,按需执行
把每个条件写成接受DataFrame为参数的函数,内部先检查所需列是否存在,再执行判断逻辑,不存在时可返回全False或自定义提示。
import pandas as pd df = pd.DataFrame( { 'Date' : ['11-01-2022', '11-01-2022', '11-01-2022', '12-01-2022', '12-01-2022', '12-01-2022'], 'Amount' : [190, 50, 55, 10, 80, 90], 'Category' : ['bill', 'grocery', 'shopping', 'grocery', 'bill', 'grocery'] } ) # 定义条件函数,顺便修正原示例中Date的判断逻辑 def december_amount_over_20(df): return (df['Date'].str.split('-').str[0] == '12') & (df['Amount'] > 20) def year_is_2022(df): if 'Year' not in df.columns: return pd.Series([False]*len(df), index=df.index) return df['Year'] == 2022 # 存储条件:键为条件名称,值为对应函数 conditions = { 'december_amount_over_20': december_amount_over_20, 'year_is_2022': year_is_2022 } # 调用条件:遍历需要评估的条件,传入DataFrame执行 for cond_name, cond_func in conditions.items(): result = cond_func(df) print(f"{cond_name} 结果:\n{result}\n")
方法二:存储条件表达式,动态检查执行
如果不想写太多函数,可以把条件所需列和表达式用字符串存储,调用时先校验列是否存在,再用eval动态执行(注意:eval存在安全风险,仅在可控场景下使用)。
# 存储条件:键为条件名称,值为(所需列列表, 表达式字符串) conditions = { 'december_amount_over_20': (['Date', 'Amount'], "(df['Date'].str.split('-').str[0] == '12') & (df['Amount'] > 20)"), 'year_is_2022': (['Year'], "df['Year'] == 2022") } for cond_name, (required_cols, expr) in conditions.items(): # 检查所有必需列是否存在 if all(col in df.columns for col in required_cols): result = eval(expr) print(f"{cond_name} 结果:\n{result}\n") else: missing_cols = [col for col in required_cols if col not in df.columns] print(f"{cond_name} 跳过:缺少列 {missing_cols}\n")
方法三:用try-except捕获错误
在生成条件时直接捕获AttributeError,适合简单场景,但可读性不如前两种方法。
conditions = {} # 添加第一个条件 try: conditions['december_amount_over_20'] = (df['Date'].str.split('-').str[0] == '12') & (df['Amount'] > 20) except AttributeError: conditions['december_amount_over_20'] = pd.Series([False]*len(df), index=df.index) # 添加第二个条件 try: conditions['year_is_2022'] = df['Year'] == 2022 except AttributeError: conditions['year_is_2022'] = pd.Series([False]*len(df), index=df.index) print("所有条件结果:\n", conditions)
内容的提问来源于stack exchange,提问作者trey hannam
相关产品推荐
相关产品推荐

