【问题标题】:Pandas fillna using groupby使用 groupby 填充熊猫
【发布时间】:2021-09-15 22:52:15
【问题描述】:

我正在尝试使用具有相似列值的行来估算/填充值。

例如,我有这个数据框:

one | two | three
1      1     10
1      1     nan
1      1     nan
1      2     nan
1      2     20
1      2     nan
1      3     nan
1      3     nan

我想使用相似的列 onetwo 的键,如果列 three 不完全是 nan,则从具有列“3”中的值的类似键的行中估算现有值。

这是我想要的结果:

one | two | three
1      1     10
1      1     10
1      1     10
1      2     20
1      2     20
1      2     20
1      3     nan
1      3     nan

可以看到键 1 和 3 不包含任何值,因为现有值不存在。

我尝试过使用groupby+fillna()

df['three'] = df.groupby(['one','two'])['three'].fillna()

这给了我一个错误。

我尝试了前向填充,这给了我相当奇怪的结果,它改为前向填充第 2 列。我正在使用此代码进行前向填充。

df['three'] = df.groupby(['one','two'], sort=False)['three'].ffill()

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    如果每组只有一个非 NaN 值,每组使用ffill(前向填充)和bfill(后向填充),所以需要applylambda

    df['three'] = df.groupby(['one','two'], sort=False)['three']
                    .apply(lambda x: x.ffill().bfill())
    print (df)
       one  two  three
    0    1    1   10.0
    1    1    1   10.0
    2    1    1   10.0
    3    1    2   20.0
    4    1    2   20.0
    5    1    2   20.0
    6    1    3    NaN
    7    1    3    NaN
    

    但是如果每个组有多个值并且需要用某个常量替换 NaN - 例如mean 分组:

    print (df)
       one  two  three
    0    1    1   10.0
    1    1    1   40.0
    2    1    1    NaN
    3    1    2    NaN
    4    1    2   20.0
    5    1    2    NaN
    6    1    3    NaN
    7    1    3    NaN
    
    df['three'] = df.groupby(['one','two'], sort=False)['three']
                    .apply(lambda x: x.fillna(x.mean()))
    print (df)
       one  two  three
    0    1    1   10.0
    1    1    1   40.0
    2    1    1   25.0
    3    1    2   20.0
    4    1    2   20.0
    5    1    2   20.0
    6    1    3    NaN
    7    1    3    NaN
    

    【讨论】:

    • @jezrael:有什么理由强制在您的答案中使用apply?我问是因为我直接尝试了 ffillbfill 并返回正确的结果:df['three'] = df.groupby(['one', 'two'])['three'].ffill().bfill()
    • @Andy L. 它工作正常,因为最后一组只是 NaN 组。如果仅更改第一个 NaN 组的样本数据(10 到 NaN),您的解决方案将失败。原因是 last bfill 不是按组工作,而是按系列返回 groupby +ffill。
    • 啊,我忘记了 bfill 回填来自 ffill 的输出系列,而不是 groupby。感谢您的回答
    • 请问,我怎样才能将df['three'] = df.groupby(['one','two'], sort=False)['three'].apply(lambda x: x.ffill().bfill()) 应用于多个列three, four, five, etc 而不是仅需要groupby onetwo 和fillna 的three
    • @ahbon - 使用 cols = ['three','four','five']df[cols] = df.groupby(['one','two'], sort=False)[cols].apply(lambda x: x.ffill().bfill())
    【解决方案2】:

    您可以按缺失值的列对数据进行排序,然后按 groupby 和 forwardfill:

    df.sort_values('three', inplace=True)
    df['three'] = df.groupby(['one','two'])['three'].ffill()
    

    【讨论】:

      猜你喜欢
      • 2020-11-06
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2019-07-12
      • 2021-03-18
      • 2017-08-04
      • 1970-01-01
      • 2019-02-24
      相关资源
      最近更新 更多