使用先前有效值的趋势在 Pandas Dataframe 中填充 NaN

问题描述

我试图通过分组来填补数据中的空白,然后使用先前数据点的趋势来预测缺失值是什么。

df

Group  Week  Value
B      1     5
B      2     6
B      3     NaN
B      4     NaN
B      5     NaN
B      6     8
B      7     8
B      8     7
B      9     6
B      10    NaN

图形上看起来像这样: Initial df plot

一旦所需的功能发生,数据框将如下所示:

Group  Week  Value
B      1     5
B      2     6
B      3     7
B      4     8
B      5     9
B      6     8
B      7     8
B      8     7
B      9     6
B      10    5.5

此处以图形方式显示了查找这些 NaN 值的先前点的趋势: NaN values calculated

本示例中的前三个 NaN 值是通过简单地绘制值 56、找到线性方程 (y = mx + c) 并将 x 拟合为周来计算 y 来找到的.将对所有 NaN 值执行相同的过程

我尝试过插值 (df = df.groupby('Group').apply(lambda group: group.interpolate(method='index')) 但这显然会查看下一个有效数据点并将其包含在计算中,我试图避免这种情况

可能值得注意的是,我使用的数据框有 200,000 行和 4,000 个组!

解决方法

您可以创建子组系列 g 并将 method="spline"order=1 传递给 interpolate

g = df['Value'].mask(df['Value'].notnull(),df['Value'].isnull().cumsum()).ffill()
df['Value'] = (df.groupby(['Group',g])['Value']
                 .apply(lambda x: x.interpolate(method="spline",order=1)))
df
Out[1]: 
  Group  Week  Value
0     B     1    5.0
1     B     2    6.0
2     B     3    7.0
3     B     4    8.0
4     B     5    9.0
5     B     6    8.0
6     B     7    8.0
7     B     8    7.0
8     B     9    6.0
9     B    10    5.5

获取 g 的中间步骤如下所示。

g = df['Value'].mask(df['Value'].notnull(),df['Value'].isnull().cumsum()).ffill()
g
Out[1]: 
0    0.0
1    0.0
2    0.0
3    0.0
4    0.0
5    3.0
6    3.0
7    3.0
8    3.0
9    3.0

数字基本上只是创建子组。我的方法是实现这一目标的一种方法。


根据您的评论,我创建了一个 mask m 来计算大小为 1 的组。然后,我使用 fillna() 组合单独的方法:

df = pd.DataFrame({'Group': {0: 'A',1: 'B',2: 'B',3: 'B',4: 'B',5: 'B',6: 'B',7: 'B',8: 'B',9: 'B'},'Week': {0: 1,1: 2,2: 3,3: 4,4: 5,5: 6,6: 7,7: 8,8: 9,9: 10},'Value': {0: 5.0,1: 6.0,2: np.nan,3: np.nan,4: np.nan,5: 8.0,6: 8.0,7: 7.0,8: 6.0,9: np.nan}})
g = df['Value'].iloc[1:].mask(df['Value'].notnull(),df['Value'].isnull().cumsum()).ffill()
m = df.groupby(['Group',g])['Value'].transform('count') > 1
v1 = (df[m].groupby(['Group',g])['Value']
                     .apply(lambda x: x.interpolate(method="spline",order=1)))
v2 = (df.groupby(['Group',g])['Value']
                     .apply(lambda x: x.interpolate(method="index")))
df['Value'] = df['Value'].fillna(v1).fillna(v2)
df

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...