基于Pandas列头与列值条件更新指定列的技术求助
Pandas实现基于列头与列值条件更新指定列的方案
输入示例
import pandas as pd import numpy as np df_in = pd.DataFrame({ 'A': ['x', 'y', 'z', 'w', 'u'], 'B': ['a', 'b', 'c', 'd', 'q'], 'ind': [2, 2, 2, 2, 2], 'M1P': [0, np.nan, 0, 0, 0], 'M2P': [0, np.nan, np.nan, 0, 0], 'M3P': [3, np.nan, 0, 0, 0], 'M4P': [5, 7, 3, np.nan, np.nan], 'M5P': [9, 11, 3, 8, 0] })
逻辑规则
- 根据
ind列的值确定目标列:ind=x对应MxP列(x范围1-5) - 若目标列值为0、NaN或空,依次从后续的
Mx+1P、Mx+2P…M5P中取第一个非0且非NaN的值替换 - 若后续所有列都不符合条件,目标列保持原值;
ind=5时不做任何替换
实现思路
- 先筛选出所有
MxP格式的列并按顺序排序,方便后续通过索引快速定位目标列和后续列 - 遍历每一行数据:
- 如果
ind等于5,直接返回原行,不做处理 - 检查目标列的值:如果值既不是0也不是NaN,直接保留原行
- 若需要替换,从目标列的下一列开始向后遍历,找到第一个符合条件的非0非NaN值,替换到目标列
- 若后续列都没有符合条件的值,保持目标列原值不变
- 如果
代码实现
import pandas as pd import numpy as np # 构造输入DataFrame df_in = pd.DataFrame({ 'A': ['x', 'y', 'z', 'w', 'u'], 'B': ['a', 'b', 'c', 'd', 'q'], 'ind': [2, 2, 2, 2, 2], 'M1P': [0, np.nan, 0, 0, 0], 'M2P': [0, np.nan, np.nan, 0, 0], 'M3P': [3, np.nan, 0, 0, 0], 'M4P': [5, 7, 3, np.nan, np.nan], 'M5P': [9, 11, 3, 8, 0] }) # 提取所有MxP格式的列并按顺序排序 m_cols = sorted([col for col in df_in.columns if col.startswith('M') and col.endswith('P')]) # 定义处理单行数据的函数 def update_target_row(row): ind_val = row['ind'] # ind=5时直接返回原行 if ind_val == 5: return row target_col = f'M{ind_val}P' target_val = row[target_col] # 目标值无需替换的情况:非NaN且不等于0 if pd.notna(target_val) and target_val != 0: return row # 获取目标列在MxP列表中的索引 target_idx = m_cols.index(target_col) # 遍历后续列寻找第一个符合条件的值 for col in m_cols[target_idx+1:]: col_val = row[col] if pd.notna(col_val) and col_val != 0: row[target_col] = col_val break # 找到后立即停止遍历 return row # 应用函数到每一行 df_out = df_in.apply(update_target_row, axis=1) # 打印输出结果 print(df_out)
输出结果
A B ind M1P M2P M3P M4P M5P 0 x a 2 0.0 3.0 3.0 5.0 9 1 y b 2 NaN 7.0 NaN 7.0 11 2 z c 2 0.0 3.0 0.0 3.0 3 3 w d 2 0.0 8.0 0.0 NaN 8 4 u q 2 0.0 0.0 0.0 NaN 0
补充说明
- 代码通过
startswith('M')和endswith('P')筛选目标列,即使后续新增M6P等同格式列,也能自动适配 - 使用
pd.notna()准确判断非NaN值,同时排除0值,严格符合需求条件 - 遍历后续列时找到第一个符合条件的值就停止,保证处理效率
内容的提问来源于stack exchange,提问作者Stan
相关产品推荐
相关产品推荐

