【问题标题】:How do you fill NaN with mean of a subset of a group?你如何用一组子集的平均值填充 NaN?
【发布时间】:2026-02-12 20:05:02
【问题描述】:

我有一个数据框,其中包含yeartype 的一些值。我想用特定类型的那一年值的平均值替换每年的所有 NaN 值。我想以最优雅的方式做到这一点。我正在处理大量数据,因此减少计算量也会很好。

例子:

df =pd.DataFrame({'year':[1,1,1,2,2,2],
                  'type':[1,1,2,1,1,2],
             'val':[np.nan,5,10,100,200,np.nan]})

我希望将所有类型的所有 nan 替换为所有类型 1 的相应年份平均值。

在本例中,第一行 NaN 应替换为 5,最后一行应替换为 150。

这只会填充类型 1 缺失的值,而不是类型 2

df[val]=df[val].fillna(df.query('type==1').groupby('year')[val].transform('mean'))

【问题讨论】:

    标签: python pandas pandas-groupby fillna


    【解决方案1】:

    你想要map:

    # calculate mean val of type 1 by year
    s = df[df['type'].eq(1)].groupby('year')['val'].mean()
    
    # replace `year` by the above mean, and fill in the Nan
    df['val'] = df['val'].fillna(df['year'].map(s))
    

    输出:

       year  type    val
    0     1     1    5.0
    1     1     1    5.0
    2     1     2   10.0
    3     2     1  100.0
    4     2     1  200.0
    5     2     2  150.0
    

    【讨论】:

    • s 的打高尔夫球版本:df.groupby(['type', 'year']).val.mean().xs(1)注意我说的是“打高尔夫球”而不是“更好”(-:
    【解决方案2】:

    使用fillna 和匹配索引

    df['val'] = (df.set_index('year').val
                  .fillna(df.query('type == 1').groupby(['year']).val.mean())
                  .values)
    

      year  type    val
    0     1     1    5.0
    1     1     1    5.0
    2     1     2   10.0
    3     2     1  100.0
    4     2     1  200.0
    5     2     2  150.0
    

    【讨论】:

      【解决方案3】:

      masktransform

      df.fillna({'val': df.val.mask(df.type.ne(1)).groupby(df.year).transform('mean')})
      
         year  type    val
      0     1     1    5.0
      1     1     1    5.0
      2     1     2   10.0
      3     2     1  100.0
      4     2     1  200.0
      5     2     2  150.0
      

      【讨论】:

      • 很好地使用mean()na高尔夫版 df.val.where(df['type'].eq(1)) :D