我的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行。
答案 0 :(得分:2)
让DateTimeIndex与resample
一起使用。
首先,我们需要将列t转换为datetime dtype并将列t设置为索引。
接下来,我们groupby
和resample
每周填补数据空缺:
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
然后,您可以使用ffill
和dt.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