如何在np.where中处理含可选None值的多条件判断?
问题描述
我需要给DataFrame新增一个基于条件的列,已经在外部定义了如下条件列表:
conditions = [ {"year": 2016, "price": 30000, "fuel": "Petrol", "result": 12}, {"year": 2017, "price": 45000, "fuel": "Elektricity", "result": 18}, {"year": 2018, "price": None, "fuel": "Petrol", "result": 14} ]
目前我用这段代码生成新列:
df['new_column'] = np.where( (df['year'] == cond['year']) & (df['price'] > cond['price']) & (df['fuel description'] == cond['fuel']), cond['result'], df['new_column'] )
但条件里可能存在None值(比如示例中2018年的price),这时需要忽略该条件,对应的代码要去掉价格判断的部分:
df['new_column'] = np.where( (df['year'] == cond['year']) & (df['fuel description'] == cond['fuel']), cond['result'], df['new_column'] )
而且可能有多个条件为None的情况,我不想写一堆if-else分支,想知道有没有办法在公式里自动忽略值为None的条件,而不是只能像下面这样处理:
if cond['price'] is not None: df['new_column'] = np.where( (df['year'] == cond['year']) & (df['price'] > cond['price']) & (df['fuel description'] == cond['fuel']), cond['result'], df['new_column'] ) else: df['new_column'] = np.where( (df['year'] == cond['year']) & (df['fuel description'] == cond['fuel']), cond['result'], df['new_column'] )
解决方案
可以通过动态构建条件表达式自动忽略None值的条件,无需编写大量if-else分支。核心逻辑是遍历每个条件字典的键值对,仅保留非None的条件,再将这些条件用逻辑与(&)拼接。
基础实现代码
import numpy as np import pandas as pd # 示例DataFrame df = pd.DataFrame({ 'year': [2016, 2017, 2018, 2019], 'price': [35000, 50000, 28000, 32000], 'fuel description': ['Petrol', 'Elektricity', 'Petrol', 'Diesel'], 'new_column': [0, 0, 0, 0] # 初始化新列 }) conditions = [ {"year": 2016, "price": 30000, "fuel": "Petrol", "result": 12}, {"year": 2017, "price": 45000, "fuel": "Elektricity", "result": 18}, {"year": 2018, "price": None, "fuel": "Petrol", "result": 14} ] # 遍历每个条件规则 for cond in conditions: condition_parts = [] # 逐个判断字段是否为None,非None则生成对应布尔表达式 if cond['year'] is not None: condition_parts.append(df['year'] == cond['year']) if cond['price'] is not None: condition_parts.append(df['price'] > cond['price']) if cond['fuel'] is not None: condition_parts.append(df['fuel description'] == cond['fuel']) # 拼接所有条件为最终判断表达式 final_condition = np.logical_and.reduce(condition_parts) # 更新新列 df['new_column'] = np.where(final_condition, cond['result'], df['new_column']) print(df)
代码说明
- 遍历每个条件字典,对
year、price、fuel字段逐一判断是否为None,非None则生成对应的布尔判断表达式,加入条件列表。 - 用
np.logical_and.reduce()将所有条件表达式拼接成最终的逻辑与判断,自动忽略所有None对应的条件。 - 用
np.where()根据最终条件更新新列,无论有多少个None条件,都无需额外分支判断。
扩展优化(适配更多字段)
如果需要支持更多条件字段,可以通过映射字典统一管理字段与判断逻辑,避免重复代码:
import numpy as np import pandas as pd df = pd.DataFrame({ 'year': [2016, 2017, 2018, 2019], 'price': [35000, 50000, 28000, 32000], 'fuel description': ['Petrol', 'Elektricity', 'Petrol', 'Diesel'], 'new_column': [0, 0, 0, 0] }) conditions = [ {"year": 2016, "price": 30000, "fuel": "Petrol", "result": 12}, {"year": 2017, "price": 45000, "fuel": "Elektricity", "result": 18}, {"year": 2018, "price": None, "fuel": "Petrol", "result": 14} ] # 定义字段与对应判断逻辑的映射 condition_mappings = { 'year': lambda df_val, cond_val: df_val == cond_val, 'price': lambda df_val, cond_val: df_val > cond_val, 'fuel': lambda df_val, cond_val: df_val == cond_val } for cond in conditions: condition_parts = [] for key, judge_func in condition_mappings.items(): cond_val = cond.get(key) if cond_val is not None: # 处理字段名与DataFrame列名不一致的情况(如fuel对应fuel description) df_col = 'fuel description' if key == 'fuel' else key condition_parts.append(judge_func(df[df_col], cond_val)) final_condition = np.logical_and.reduce(condition_parts) df['new_column'] = np.where(final_condition, cond['result'], df['new_column']) print(df)
新增条件字段时,只需在condition_mappings中添加对应的字段和判断逻辑即可,代码扩展性更强。
内容的提问来源于stack exchange,提问作者Tim Gast
相关产品推荐
相关产品推荐

