带有衰减的 Pandas 数据帧前向填充
Posted
技术标签:
【中文标题】带有衰减的 Pandas 数据帧前向填充【英文标题】:Pandas dataframe forward-fill with decay 【发布时间】:2018-12-02 04:23:12 【问题描述】:我正在运行 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
【问题讨论】:
嗨,衰变在这里应该如何工作?只有之前值的一半? 是的,例如,只是先前值的一半。我添加了常规的ffill()
输出和比较所需的输出。
无论如何您都可以要求将其添加为github 的功能。
【参考方案1】:
是的,没有简单的方法可以做到这一点。我建议一次做一列,使用groupby
和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
【讨论】:
末尾有一个额外的括号并返回此错误NameError: name 'x' is not defined
【参考方案2】:
有一个矢量解决方案。它部分使用了这个answer
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
进行比较应该会很有趣。
【讨论】:
以上是关于带有衰减的 Pandas 数据帧前向填充的主要内容,如果未能解决你的问题,请参考以下文章
在 pandas 数据帧中使用前向和后向填充填充缺失值(ffill 和 bfill)
pandas使用shift偏移dataframe中时间列计算相邻两列的时间差如果shift参数为-1则指定列向上移动1个位置,使用前向填充进行缺失值填充