如何用常数0填充Pandas DataFrame内部NaN并设置limit=2
Pandas 内部NaN填充(带数量限制)
原始DataFrame
import pandas as pd import numpy as np df = pd.DataFrame({ 'col1': [100, np.nan, np.nan, 100, np.nan, np.nan, np.nan], 'col2': [np.nan, 100, np.nan, np.nan, np.nan, 100, np.nan] })
输出:
col1 col2 0 100.0 NaN 1 NaN 100.0 2 NaN NaN 3 100.0 NaN 4 NaN NaN 5 NaN 100.0 6 NaN NaN
目标转换结果
col1 col2 0 100.0 NaN 1 0.0 100.0 2 0.0 0.0 3 100.0 0.0 4 NaN NaN 5 NaN 100.0 6 NaN NaN
需求说明
- 仅填充两个非NaN值之间的内部区域中的NaN,用常数
0替换 - 连续NaN填充上限为
limit=2:若区间内连续NaN超过2个,仅替换前2个,剩余NaN保留
解决方案
通过自定义函数标记有效填充区间,结合数量限制实现:
def fill_inner_nan(col, fill_val=0, limit=2): non_nan = col.notna() non_nan_idx = non_nan[non_nan].index # 非NaN值不足2个,无内部区间可填充 if len(non_nan_idx) < 2: return col # 遍历每一对相邻非NaN值的区间 for start, end in zip(non_nan_idx[:-1], non_nan_idx[1:]): # 定位区间内的行(排除两端非NaN值) interval_mask = (col.index > start) & (col.index < end) # 计算区间内NaN总数 total_nans = col[interval_mask].isna().sum() # 实际填充数量取limit和总数的最小值 fill_count = min(limit, total_nans) # 标记区间内前fill_count个NaN的位置 fill_mask = col[interval_mask].isna().cumsum() <= fill_count # 执行填充 col.loc[interval_mask & fill_mask] = fill_val return col # 对所有列应用填充逻辑 result_df = df.apply(fill_inner_nan, fill_val=0, limit=2) print(result_df)
逻辑说明
- 先识别列中的非NaN位置,提取其索引
- 若列中非NaN值少于2个,直接返回原列(无内部区间)
- 遍历每一对相邻非NaN值,确定它们之间的内部区间
- 计算区间内NaN数量,按limit限制填充数量
- 精准定位区间内前N个NaN的位置,替换为0
- 对DataFrame每一列应用该函数,得到目标结果
内容的提问来源于stack exchange,提问作者data-monkey
相关产品推荐
相关产品推荐

