【问题标题】:Efficient solution for forward filling missing values in a pandas dataframe column?前向填充熊猫数据框列中缺失值的有效解决方案?
【发布时间】:2017-08-21 21:25:18
【问题描述】:

我需要在组内的数据框列中转发填充值。我应该注意,组中的第一个值不会因构造而丢失。我目前有以下解决方案。

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, 2, np.nan, np.nan]})

# desired output
a   b
1   1
1   1
2   2
2   2
2   2

这是我目前尝试过的三种解决方案。

# really slow solutions
df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill'))
df['b'] = df.groupby('a')['b'].fillna(method='ffill')

# much faster solution, but more memory intensive and ugly all around
tmp = df.drop_duplicates('a', keep='first')
df.drop('b', inplace=True, axis=1)
df = df.merge(tmp, on='a')

所有这三个都产生了我想要的输出,但是前两个在我的数据集上花费了很长时间,第三个解决方案更占用内存并且感觉相当笨重。还有其他方法可以向前填充列吗?

【问题讨论】:

  • 您的真实数据是否像示例数据那样按组排序?如果是这样,您应该能够只使用常规的ffill,因为您在组中的第一个值始终存在,即df['b'] = df['b'].ffill()
  • 哇。我完全错过了。排序后速度很快。谢谢@root!

标签: python pandas missing-data


【解决方案1】:

您需要按df.sort_values(['a', 'b']).ffill() 两列排序以确保稳健性。如果np.nan 留在组内的第一个位置,ffill 将使用前一组中的值填充该位置。因为np.nan 将放置在任何排序的末尾,所以同时按ab 进行排序可确保您不会将np.nan 放在任何组的前面。然后您可以使用初始索引.loc.reindex 来取回您的原始订单。

这显然会比其他提案慢一点...但是,我认为它会正确而其他提案不正确。

演示

考虑数据框df

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, np.nan, 2, np.nan]})

print(df)

   a    b
0  1  1.0
1  1  NaN
2  2  NaN
3  2  2.0
4  2  NaN

试试

df.sort_values('a').ffill()

   a    b
0  1  1.0
1  1  1.0
2  2  1.0  # <--- this is incorrect
3  2  2.0
4  2  2.0

改为

df.sort_values(['a', 'b']).ffill().loc[df.index]

   a    b
0  1  1.0
1  1  1.0
2  2  2.0
3  2  2.0
4  2  2.0

特别说明
如果整个组都有缺失值,这仍然是不正确的

【讨论】:

    【解决方案2】:

    直接使用 ffill() 会得到最好的结果。这是比较

    %timeit df.b.ffill(inplace = True)
    best of 3: 311 µs per loop
    
    %timeit df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill'))
    best of 3: 2.34 ms per loop
    
    %timeit df['b'] = df.groupby('a')['b'].fillna(method='ffill')
    best of 3: 4.41 ms per loop
    

    【讨论】:

      【解决方案3】:

      这个呢

      df.groupby('a').b.transform('ffill')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-06
        • 1970-01-01
        • 1970-01-01
        • 2016-04-30
        • 2017-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多