【问题标题】:Fillna (forward fill) on a large dataframe efficiently with groupby?使用 groupby 有效地在大型数据帧上填充(前向填充)?
【发布时间】:2017-04-08 10:15:28
【问题描述】:

在大型数据帧中转发填充信息的最有效方法是什么?

我从日常文件中合并了大约 600 万行 x 50 列的维度数据。我删除了重复项,现在我有大约 200,000 行唯一数据,可以跟踪其中一个维度发生的任何变化。

不幸的是,一些原始数据被弄乱了并且有空值。如何有效地用之前的值填充空数据?

id       start_date   end_date    is_current  location  dimensions...
xyz987   2016-03-11   2016-04-02  Expired       CA      lots_of_stuff
xyz987   2016-04-03   2016-04-21  Expired       NaN     lots_of_stuff
xyz987   2016-04-22          NaN  Current       CA      lots_of_stuff

这是数据的基本形状。问题是某些维度不应该是空白的(这是原始数据中的错误)。例如,对于前一行,该行的位置已填写,但在下一行中为空白。我知道该位置没有改变,但它正在将其捕获为唯一行,因为它是空白的。

我假设我需要使用 ID 字段进行分组。这是正确的语法吗?我需要列出数据框中的所有列吗?

cols = [list of all of the columns in the dataframe]
wfm.groupby(['id'])[cols].fillna(method='ffill', inplace=True)

在 200,000 行数据框中大约有 75,000 个唯一 ID。我试着做一个

df.fillna(method='ffill', inplace=True)

但我需要根据 ID 执行此操作,并且我想确保我尽可能高效(我的计算机需要很长时间才能读取所有这些文件并将其合并到内存中)。

【问题讨论】:

    标签: pandas


    【解决方案1】:

    直接在 groupby 对象上执行fillna 可能很有效:

    df = df.groupby(['id']).fillna(method='ffill')
    

    引用的方法 here 在文档中。

    【讨论】:

    • 我一直在使用 lambda 函数,但我会试试这个。有道理。
    【解决方案2】:

    如何向前填充每个组?

     df = df.groupby(['id'], as_index=False).apply(lambda group: group.ffill())
    

    【讨论】:

    • 这将维护数据框中的所有列,对吗?所以我不必像在上面的示例代码中那样指定它们的列表?
    • 正确。它将转发填充除id之外的所有内容。
    • 谢谢你,df = df.groupby(['id']).fillna(method='ffill') 下面的代码为我返回了一个真假布尔值,知道为什么这与那个不同吗?
    【解决方案3】:

    github/jreback:这是 #7895 的欺骗。 .ffill 没有在 cython 的 groupby 操作中实现(尽管它当然可以),而是在每个组上调用 python 空间。 这是一个简单的方法来做到这一点。 网址:https://github.com/pandas-dev/pandas/issues/11296

    根据 jreback 的回答,当你做一个 groupby 时, ffill() 没有优化,但 cumsum() 是。试试这个:

    df = df.sort_values('id')
    df.ffill() * (1 - df.isnull().astype(int)).groupby('id').cumsum().applymap(lambda x: None if x == 0 else 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      • 2018-12-02
      • 2023-03-03
      相关资源
      最近更新 更多