2

我正在运行 Python 3.5 和 Pandas v 0.19.2。我有一个如下所示的数据框。向前填充缺失值是直截了当的。

import pandas as pd
import numpy as np

d = {'A': np.array([10, np.nan, np.nan, -3, np.nan, 4, np.nan, 0]),
     'B': np.array([np.nan, np.nan, 5, -3, np.nan, np.nan, 0, np.nan ])}
df = pd.DataFrame(d)
df_filled = df.fillna(axis='index', method='ffill')
print(df_filled)
Out[8]: 
      A    B
0  10.0  NaN
1  10.0  NaN
2  10.0  5.0
3  -3.0 -3.0
4  -3.0 -3.0
5   4.0 -3.0
6   4.0  0.0
7   0.0  0.0

我的问题是:用衰减实现前向填充的最佳方法是什么?我理解pd.ffill()并且pd.fillna()不支持这个。例如,我所追求的输出如下(与上面的常规 ffill 相比),其中每个周期的值都减半:

Out[5]: 
      A    B
0  10.0  NaN
1   5.0  NaN
2   2.5  5.0
3  -3.0 -3.0
4  -1.5 -1.5
5   4.0 -0.75
6   2.0  0.0
7   0.0  0.0
4

2 回答 2

4

是的,没有简单的方法可以做到这一点。我建议一次做一列,使用groupbyand apply

for c in df:
    df[c] = df[c].groupby(df[c].notnull().cumsum()).apply(
        lambda y: y.ffill() / 2 ** np.arange(len(y))
    )

df
      A     B
0  10.0   NaN
1   5.0   NaN
2   2.5  5.00
3  -3.0 -3.00
4  -1.5 -1.50
5   4.0 -0.75
6   2.0  0.00
7   0.0  0.00
于 2018-06-22T16:48:44.920 回答
3

有一个矢量解决方案。它部分使用了这个答案

import pandas as pd
import numpy as np

d = {'A': np.array([10, np.nan, np.nan, -3, np.nan, 4, np.nan, 0]),
     'B': np.array([np.nan, np.nan, 5, -3, np.nan, np.nan, 0, np.nan ])}
df = pd.DataFrame(d)

decay_rate = 2

ddf = df.isnull().cumsum().diff().fillna(0)
ddf = ddf!=0
ddf = ddf.cumsum() - ddf.cumsum()\
                        .where(~ddf)\
                        .ffill()\
                        .fillna(0)
df_filled = df.ffill()/(ddf * decay_rate).replace(0, 1)

编辑:在我的实验中,这个解决方案比其他解决方案快 1.8 倍。将结果与完整的df.

于 2018-06-22T17:55:05.510 回答