【问题标题】:Fill N/A between values, by group, in pandas or numpy在 pandas 或 numpy 中按组填充值之间的 N/A
【发布时间】:2017-06-28 15:12:22
【问题描述】:

我有一个看起来像的 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 中的内容允许不同的开始和结束时间。在本例中,1,3 缺少 20170108,2,3 缺少 20170115 和 20170122。所以填充的 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 的解决方案效果很好。但是,在 2000 万个 obs 的样本数据集中,df 需要 30 多分钟才能扩展到 3000 万行以进行第一次索引重置。

【问题讨论】:

    标签: python pandas numpy dataframe panel


    【解决方案1】:

    让我们将 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
    

    【讨论】:

    • 感谢您的建议!有什么加速技巧吗?也许我需要遍历 i 或 j,因为在 2000 万个样本数据集上,已经过去了 25 分钟,但它仍在继续运行。另外,如果我还有另一列 y,我也想扩展它,但仍保留为 NaN。我只是将 ['x','y'] 添加到第一个重采样中。但是,我如何将 y 保留为 NaN 但继承 x?
    • 哇......这是一些数据。也许一个 numpy 解决方案会更好。我会在您的问题中删除“时间序列”标签并添加 numpy.这里有一些非常优秀的 numpy 人。
    • 谢谢斯科特。 [x,y] 问题的任何解决方案?我不反对通过 i,j 和多处理进行拆分。实际上有多个 dfs(一年一年),因此拆分将有利于将所有 i,j 跨年组合,然后进行结转。当前的解决方案会在一个文件中错过 2016 年 12 月 7 日的结束日期,而在另一个文件中错过 2017 年 1 月 3 日的开始日期(12 月填写缺失)。
    • df = df.set_index('t').groupby(['i','j'])['x','y'].resample('W').asfreq( ) df['x'] = df.x.ffill() df = df.reset_index()
    • 我的代码失败了,因为我的 obs 不在星期天,所以“W”导致所有的 NaN 和日期的变化。 “W-SAT”虽然有效。谢谢。
    猜你喜欢
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 2015-11-21
    • 2018-06-23
    • 1970-01-01
    • 2013-09-09
    • 2021-02-13
    相关资源
    最近更新 更多