使用.shift()和条件语句填充DataFrame空值出错,求排查原因
问题分析与修复方案
咱们先明确你的核心需求:当A列出现空值时,只要对应的B值没有发生增长(也就是和最近一次A=1时的B值保持一致),就把这个空值填成0。
你的原代码没得到预期结果,大概率是shift()的对比逻辑没匹配上你实际的业务场景,咱们来拆解问题并给出修复方案:
为啥原代码会出问题?
你写的df['B'] == df['B'].shift()是拿当前行的B和前一行的B做对比,但你的需求本质是要和最近的A=1的行的B做对比,这两个逻辑在某些场景下会不匹配:
- 比如如果空值前面有连续多个0的行,原代码能正常工作,但如果空值直接跟在A=1的行后面(比如
A=1,B=21之后是NaN,B=21),原代码也能填0,但如果你的数据索引不连续(比如删除过行),shift()会基于索引偏移而不是行位置,这时候就会拿错误的行来对比,导致条件不成立。
正确的实现方式
我们可以先把所有A=1的行的B值提取出来,然后向前填充,这样每一行都能拿到最近一次A=1时的B值,再用这个值和当前行的B对比,就能精准判断是否要填0:
import pandas as pd import numpy as np # 你的示例数据 df = pd.DataFrame({ 'A': [1, 0, np.nan, 1, 1, 0], 'B': [21, 21, 21, 25, 28, 28] }) # 第一步:生成临时列,存储每行对应的最近一次A=1的B值 df['last_A1_B'] = df.loc[df['A'] == 1, 'B'].reindex(df.index).ffill() # 第二步:按照需求填充A列的空值 df['A'] = np.where( (df['A'].isnull()) & (df['B'] == df['last_A1_B']), 0, df['A'] ) # 删掉临时列(可选) df.drop('last_A1_B', axis=1, inplace=True) print(df)
运行这段代码后,你会得到预期的结果:
A B 0 1.0 21 1 0.0 21 2 0.0 21 3 1.0 25 4 1.0 28 5 0.0 28
额外优化
如果你的业务规则是只有A=1时B才会增长,A=1时B一定增长(不会出现A=1但B不变的情况),那逻辑还能更简单:直接把所有A的空值填成0就行,因为空值对应的B肯定和最近一次A=1的B一致,代码可以简化成:
df['A'] = df['A'].fillna(0)
内容的提问来源于stack exchange,提问作者chink
相关产品推荐
相关产品推荐

