Pandas工作日时间索引下,0值列填充的非重索引解决方案求助
解决方案:保留日期索引的有效值填充
核心实现:用ffill()结合条件判断完成需求
你的需求本质是用最近的非零有效值填充0值,pandas原生的ffill()(前向填充)可以完美实现"取上一个有效值"的逻辑,全程不需要修改日期索引,一行代码就能搞定:
df['ColB'] = df['ColA'].mask(df['ColA'] == 0).ffill()
或者等价的where写法,逻辑完全一致:
df['ColB'] = df['ColA'].where(df['ColA'] != 0).ffill()
代码逻辑说明
mask(df['ColA'] == 0):将ColA中所有为0的位置替换为NaNffill():向前填充NaN值,自动取当前行之前最近的非NaN有效值(只按DataFrame的行顺序匹配,完全忽略日期间隔,正好对应你要的"上一个有效值",而非前一天的值)
用你的示例数据测试,代码如下:
import pandas as pd # 构造示例DataFrame data = {'ColA': [7, 3, 0, 5, 0]} index = pd.to_datetime(['2019-11-11', '2019-11-12', '2019-11-13', '2019-11-14', '2019-11-15']) df = pd.DataFrame(data, index=index) # 生成ColB列 df['ColB'] = df['ColA'].mask(df['ColA'] == 0).ffill() print(df)
输出结果完全符合预期:
ColA ColB 2019-11-11 7 7.0 2019-11-12 3 3.0 2019-11-13 0 3.0 2019-11-14 5 5.0 2019-11-15 0 5.0
如果需要将ColB转为整数类型,可追加一步:
df['ColB'] = df['ColB'].astype(int)
你之前的方法出错原因
列表推导式+Timedelta:
这种方法依赖日期的连续性,试图通过"日期减一天"取前值,但你的索引是工作日,周末/节假日不在索引内,自然会触发KeyError,逻辑本身就不符合需求。shift方法误用:
df.loc[d,'ColA']取出的是单个标量值(如numpy.int64),而shift()是Series/DataFrame的方法,不能直接作用于标量,因此会报AttributeError。即使正确对Series使用shift(1),也只是取DataFrame的上一行,虽然逻辑接近需求,但你的写法完全错误。
内容的提问来源于stack exchange,提问作者AndysPythonStuff
相关产品推荐
相关产品推荐

