基于多条件的Python分支逻辑实现求助(含DataFrame处理)
Python分支逻辑实现方案
核心需求
基于输入的DataFrame(包含l1、l2、l3、mon四列),生成output_val和output_col两列,分支逻辑规则如下:
- 当
mon < 5时:优先取l1作为output_val,output_col为'l1';若l1为NaN,优先取l3,其次取l2 - 当
5 ≤ mon ≤7时:数值从l1向l2过渡:mon=5:output_val = 0.6*l1 + 0.4*l2,output_col为'0.60*l1+0.40*l2'mon=6:output_val = 0.5*l1 + 0.5*l2,output_col为'0.50(l1+l2)';若其中一个值为NaN,则取可用值的100%(如l2为NaN则取1*l1)mon=7:output_val = 0.4*l1 + 0.6*l2,output_col为'0.40*l1+0.60*l2'
- 当
8 ≤ mon ≤10时:优先取l2作为output_val,output_col为'l2';若l2为NaN,优先取l1,其次取l3 - 当
11 ≤ mon ≤13时:数值从l2向l3过渡:mon=11:output_val = 0.6*l2 + 0.4*l3,output_col为'0.60*l2+0.40*l3'mon=12:output_val = 0.5*l2 + 0.5*l3,output_col为'0.50(l2+l3)';若其中一个值为NaN,则取可用值的100%mon=13:output_val = 0.4*l2 + 0.6*l3,output_col为'0.40*l2 + 0.60*l3'
- 当
mon ≥14时:优先取l3作为output_val,output_col为'l3';若l3为NaN,优先取l2,其次取l1 - 特殊情况:若
l1、l2、l3均为NaN,则output_val=0,output_col为' '
输入示例代码
import numpy as np import pandas as pd data = {'l1': [2,3,np.nan,3,4,1,23,5,np.nan, 100, 101, 200, 121, 431, 341], 'l2': [12,13,np.nan,13,14,np.nan,123,15,np.nan, 200, 87, 65, 23, 54, np.nan], 'l3': [np.nan,333,111,np.nan,334,111,123,5,np.nan, np.nan, 65, 154, 341, np.nan, np.nan], 'mon':[1,2,3,4,5,6,7,8,9,10, 11, 12, 13, 14, 15]} data = pd.DataFrame(data)
预期输出示例代码
output_data = {'l1': [2,3,1,3,4,1,23,5,np.nan, 100, 101, 200, 121, 431, 341], 'l2': [12,13,np.nan,13,14,np.nan,123,15,np.nan, 200, 87, 65, 23, 54, np.nan], 'l3': [np.nan,333,111,np.nan,334,111,123,5,np.nan, np.nan, 65, 154, 341, np.nan, np.nan], 'mon':[1,2,3,4,5,6,7,8,9,10, 11, 12, 13, 14, 15], 'output_val': [2,3,111, 3, 13.44, 1, 678.96, 15, 0, 200, 1357, 2502, 1882, 54, 341], 'output_col':['l1', 'l1', 'l3', 'l1', '0.60*l1+0.40*l2', '1*l1', '0.40*l1+0.60*l2', 'l2', ' ', 'l2', '0.60*l2+0.40*l3', '0.50*(l2+l3)', '0.40*l2+0.60*l3', 'l2', 'l1']} output_data = pd.DataFrame(output_data)
实现代码
import numpy as np import pandas as pd def calculate_output(row): l1, l2, l3, mon = row['l1'], row['l2'], row['l3'], row['mon'] # 处理全NaN的特殊情况 if pd.isna(l1) and pd.isna(l2) and pd.isna(l3): return 0, ' ' # mon <5 分支 if mon <5: if not pd.isna(l1): return l1, 'l1' elif not pd.isna(l3): return l3, 'l3' else: return l2, 'l2' # 5<=mon<=7 分支 elif 5 <= mon <=7: if mon ==5: val = 0.6*l1 +0.4*l2 col = '0.60*l1+0.40*l2' elif mon ==6: if pd.isna(l1): val = l2 col = '1*l2' elif pd.isna(l2): val = l1 col = '1*l1' else: val =0.5*l1 +0.5*l2 col = '0.50(l1+l2)' else: # mon==7 val =0.4*l1 +0.6*l2 col = '0.40*l1+0.60*l2' # 兜底处理计算后可能的NaN if pd.isna(val): val = l1 if not pd.isna(l1) else l2 col = '1*l1' if not pd.isna(l1) else '1*l2' return val, col # 8<=mon<=10 分支 elif 8 <= mon <=10: if not pd.isna(l2): return l2, 'l2' elif not pd.isna(l1): return l1, 'l1' else: return l3, 'l3' # 11<=mon<=13 分支 elif 11 <= mon <=13: if mon ==11: val =0.6*l2 +0.4*l3 col = '0.60*l2+0.40*l3' elif mon ==12: if pd.isna(l2): val = l3 col = '1*l3' elif pd.isna(l3): val = l2 col = '1*l2' else: val =0.5*l2 +0.5*l3 col = '0.50(l2+l3)' else: # mon==13 val =0.4*l2 +0.6*l3 col = '0.40*l2 + 0.60*l3' # 兜底处理计算后可能的NaN if pd.isna(val): val = l2 if not pd.isna(l2) else l3 col = '1*l2' if not pd.isna(l2) else '1*l3' return val, col # mon >=14 分支 else: if not pd.isna(l3): return l3, 'l3' elif not pd.isna(l2): return l2, 'l2' else: return l1, 'l1' # 应用函数到每一行 data[['output_val', 'output_col']] = data.apply(calculate_output, axis=1, result_type='expand') # 验证结果 print(data)
代码说明
- 采用
apply逐行处理,确保每个分支逻辑精准覆盖需求 - 优先处理全NaN的特殊情况,避免后续计算出现异常
- 对mon=6、mon=12的NaN特殊场景单独处理,同时为区间内其他计算结果做兜底,保证输出有效性
内容的提问来源于stack exchange,提问作者user15051990
相关产品推荐
相关产品推荐

