如何按动态规则填充DataFrame中的NaN值?
解决动态规则的DataFrame NaN填充问题
需求说明
给定包含数值和NaN的DataFrame,需按照以下规则填充:
- 找到每个非NaN值,若其后续存在连续NaN,将该非NaN值与后续所有连续NaN替换为「原值/(连续NaN数量+1)」
- 示例:第3行(值24)和第4行(NaN)替换为12(24/2);第6行(值15)、7、8行(NaN)替换为5(15/3)
示例DataFrame
import pandas as pd import numpy as np df = pd.DataFrame( {'Column 1': [10, 12, 24, np.nan, 20, 15, np.nan, np.nan, 2]}, index=range(1, 10) )
解决方案
方法一:基于分组标识的高效处理
利用cumsum()生成分组ID,将每个「非NaN+连续NaN」序列划分为同一组,再批量填充:
# 生成分组ID:每个连续的非NaN+NaN序列分配唯一ID df['group_id'] = df['Column 1'].notna().cumsum() # 遍历每个分组处理 for gid, group in df.groupby('group_id'): # 仅处理包含NaN的分组(长度>1) if len(group) > 1: original_value = group['Column 1'].iloc[0] fill_value = original_value / len(group) df.loc[group.index, 'Column 1'] = fill_value # 删除临时分组列 df.drop('group_id', axis=1, inplace=True)
方法二:逐行遍历定位分组(适合小数据量)
手动定位每个需要处理的组的起始和结束位置,再填充:
# 标记非NaN且下一行是NaN的行(即分组起始行) mask = df['Column 1'].notna() & df['Column 1'].shift(-1).isna() start_indices = df[mask].index # 遍历每个起始行处理 for idx in start_indices: current_idx = idx + 1 # 找到连续NaN的最后一行 while current_idx in df.index and pd.isna(df.loc[current_idx, 'Column 1']): current_idx += 1 end_idx = current_idx - 1 group_size = end_idx - idx + 1 fill_value = df.loc[idx, 'Column 1'] / group_size # 填充整个组 df.loc[idx:end_idx, 'Column 1'] = fill_value
处理结果
执行上述代码后,DataFrame变为:
Column 1 1 10.0 2 12.0 3 12.0 4 12.0 5 20.0 6 5.0 7 5.0 8 5.0 9 2.0
内容的提问来源于stack exchange,提问作者Haikal Yeo
相关产品推荐
相关产品推荐

