在组中,在pandas或numpy中按值填写N / A.

时间:2017-06-28 15:12:22

标签: python pandas numpy dataframe panel

我的DF看起来像

df=pd.DataFrame.from_items([('i', [1, 1, 2,2]), ('j', [3, 3, 3,3]), ('t', [20170101, 20170115, 20170108,20170129]), ('x', [1.2, 1.4, 8,8.3])])

>>> df
   i  j          t    x
0  1  3  20170101  1.2
1  1  3  20170115  1.4
2  2  3  20170108  8.0
3  2  3  20170129  8.3

列i和j标识数据的一个维度(思考人和地点),t表示i,j的另一个维度(时间)。每周的时间频率为Y,M,D格式。列x是数据(也可能是包含其他数据的列y等)。

我需要做的是填写每个i,j的缺失日期,但根据DF中的内容允许不同的开始和结束时间。在这个例子中,20170108缺少1,3,20170115和20170122缺少2,3。所以DF的填充应该如下:

>>> df
   i  j          t    x
0  1  3  20170101  1.2
1  1  3  20170108  N/A
2  1  3  20170115  1.4
3  2  3  20170108  8.0
4  2  3  20170115  N/A
5  2  3  20170122  N/A
6  2  3  20170129  8.3

实际上,更好的是将N / A替换为围绕它的平均值,或者可能只是结转最后观察到的x。对于后一种情况,这样的事情

>>> df
   i  j          t    x
0  1  3  20170101  1.2
1  1  3  20170108  1.2
2  1  3  20170115  1.4
3  2  3  20170108  8.0
4  2  3  20170115  8.0
5  2  3  20170122  8.0
6  2  3  20170129  8.3

这似乎是pd.resample的一个更复杂的版本,但我不知道如何仅在基于i,j的观察到的端点之间填写。实际的DF非常大(数百万行)。

numpy的解决方案也很棒。

更新:Scott的解决方案效果很好。但是,在20mil obs的样本数据集中,对于第一次索引重置,df需要超过30分钟才能扩展到30mil行。

1 个答案:

答案 0 :(得分:2)

让DateTimeIndex与resample一起使用。 首先,我们需要将列t转换为datetime dtype并将列t设置为索引。 接下来,我们groupbyresample每周填补数据空缺:

df=pd.DataFrame.from_items([('i', [1, 1, 2,2]), ('j', [3, 3, 3,3]), ('t', [20170101, 20170115, 20170108,20170129]), ('x', [1.2, 1.4, 8,8.3])])
df['t'] = pd.to_datetime(df.t, format=('%Y%m%d')) 

中间产出:

df.set_index('t').groupby(['i','j'])['x'].resample('W').asfreq().reset_index()

   i  j          t    x
0  1  3 2017-01-01  1.2
1  1  3 2017-01-08  NaN
2  1  3 2017-01-15  1.4
3  2  3 2017-01-08  8.0
4  2  3 2017-01-15  NaN
5  2  3 2017-01-22  NaN
6  2  3 2017-01-29  8.3

然后,您可以使用ffilldt.strftime来获得最终结果:

df = df.set_index('t').groupby(['i','j'])['x'].resample('W').ffill().reset_index()
df['t'] = df['t'].dt.strftime('%Y%m%d)

最终输出:

   i  j         t    x
0  1  3  20170101  1.2
1  1  3  20170108  1.2
2  1  3  20170115  1.4
3  2  3  20170108  8.0
4  2  3  20170115  8.0
5  2  3  20170122  8.0
6  2  3  20170129  8.3