You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中按行指定列范围填充NA值为0

问题描述

我有如下Pandas DataFrame:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'End' : ['2022-03','2022-05','2022-06'],
    '2022-01' : [1,2,np.nan],
    '2022-02' : [np.nan,3,4],
    '2022-03' : [np.nan,1,3],
    '2022-04' : [np.nan,np.nan,2],
    '2022-05' : [np.nan,np.nan,np.nan],
    '2022-06' : [np.nan,np.nan,np.nan]
})

需要填充每行的NaN值,规则为:将每行中End列指定的列及之前的列内的NaN替换为0,End列之后的列保持NaN不变。

期望输出如下:

pd.DataFrame({
    'End' : ['2022-03','2022-05','2022-06'],
    '2022-01' : [1,2,0],
    '2022-02' : [0,3,4],
    '2022-03' : [0,1,3],
    '2022-04' : [np.nan,0,2],
    '2022-05' : [np.nan,0,0],
    '2022-06' : [np.nan,np.nan,0]
})
解决方案

方法一:逐行处理(直观易懂)

先提取所有日期列并建立列名与位置的映射,再逐行根据End列的值生成填充掩码,替换对应区域的NaN:

# 提取除End外的日期列
date_cols = [col for col in df.columns if col != 'End']
# 建立列名到索引位置的映射
col_position = {col: idx for idx, col in enumerate(date_cols)}

def process_row(row):
    end_col_name = row['End']
    end_pos = col_position[end_col_name]
    # 生成掩码:标记End列及之前的所有列
    fill_mask = [i <= end_pos for i in range(len(date_cols))]
    # 对掩码覆盖区域的NaN填充0,其余保持原样
    row[date_cols] = np.where(fill_mask, row[date_cols].fillna(0), row[date_cols])
    return row

# 应用到每行得到结果
result_df = df.apply(process_row, axis=1)

方法二:向量化操作(高效适用于大数据集)

通过广播生成二维掩码矩阵,避免逐行循环,提升处理效率:

date_cols = df.columns.drop('End')
# 获取每行End对应的列索引位置
end_indices = df['End'].apply(date_cols.get_loc)
# 生成二维掩码:每行中列索引 <= 对应End位置的区域标记为True
mask = np.arange(len(date_cols)) <= end_indices[:, np.newaxis]
# 复制原数据并按掩码填充NaN
result_df = df.copy()
result_df[date_cols] = np.where(mask, result_df[date_cols].fillna(0), result_df[date_cols])

内容的提问来源于stack exchange,提问作者r0bt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 02:35:24