Pandas 用给定分组的平均值替换 nan

Posted

技术标签:

【中文标题】Pandas 用给定分组的平均值替换 nan【英文标题】:Pandas replace nan with mean value for a given grouping 【发布时间】:2016-03-18 12:25:32 【问题描述】:

我有一个大型数据集:

    period_id  gic_subindustry_id  operating_mgn_fym5  operating_mgn_fym4  317        201509            25101010           13.348150           11.745965   
682        201509            20101010           10.228725           10.473917   
903        201509            20101010           NaN                 17.700966   
1057       201509            50101010           27.858305           28.378040   
1222       201509            25502020           15.598956           11.658813   
2195       201508            25502020           27.688324           22.969760   
2439       201508            45202020           NaN                 27.145216   
2946       201508            45102020           17.956425           18.327724 

在实践中,我有数以千计的值可以追溯到 25 年前,并且有多个 (10+) 列。

我正在尝试用该时间段的 gic_industry_id 中值/平均值替换 NaN 值。

我尝试了一些类似

的方法

df.fillna(df.groupby('period_id', 'gic_subindustry_id').transform('mean')), 但这似乎非常缓慢(我在几分钟后停止了它)。

我想到它可能很慢的原因是重新计算遇到的每个 NaN 的平均值。为了解决这个问题,我认为计算每个 period_id 的平均值,然后使用它替换/映射每个 NaN 可能会更快。

means = df.groupby(['period_id', 'gic_subindustry_id']).apply(lambda x:x.mean())

输出:

                             operating_mgn_fym5  operating_mgn_fym4 operating_mgn_fym3 operating_mgn_fym2   
period_id gic_subindustry_id                                             
201509    45202030            1.622685  0.754661   0.755324  321.295665  
          45203010            1.447686  0.226571   0.334280   12.564398  
          45203015            0.733524  0.257581   0.345450   27.659407  
          45203020            1.322349  0.655481   0.468740   19.823722  
          45203030            1.461916  1.181407   1.487330   16.598534  
          45301010            2.074954  0.981030   0.841125   29.423161  
          45301020            2.621158  1.235087   1.550252   82.717147  

事实上,这要快得多(30 - 60 秒)。

但是,我正在努力弄清楚如何将 NaN 映射到这些方法。而且,确实,这是执行此映射的“正确”方式吗?速度实际上并不是最重要的,但

【问题讨论】:

【参考方案1】:

您可以使用 group-by 的结果使用 fillna,前提是数据帧具有相同的结构(由 as_index=False 给出):

df.fillna(df.groupby(['period_id', 'gic_subindustry_id'], as_index=False).mean())

#In [60]: df
#Out[60]: 
#   period_id  gic_subindustry_id  operating_mgn_fym5  operating_mgn_fym4
#0     201508            25502020           27.688324           22.969760
#1     201508            45102020           17.956425           18.327724
#2     201508            45202020                 NaN           27.145216
#3     201509            20101010           10.228725           14.087442
#4     201509            25101010           13.348150           11.745965
#5     201509            25502020           15.598956           11.658813
#6     201509            50101010           27.858305           28.378040
#7     201508            45102020           17.956425           18.327724

【讨论】:

【参考方案2】:

我认为下面的代码是正确的。

b = a.fillna(a.groupby(['period_id', 'gic_subindustry_id']).transform("mean"))

【讨论】:

以上是关于Pandas 用给定分组的平均值替换 nan的主要内容,如果未能解决你的问题,请参考以下文章

用滚动平均值或其他插值替换 NaN 或缺失值

Pandas:用前一个和下一个非缺失值的平均值动态替换 NaN 值

pandas如何使用groupby [duplicate]将NaN值替换为平均值

用相关列的平均值替换数据框中的 NaN 值的函数

通过 Pandas 中的函数替换 NaN 时索引超出范围

使用 pandas 的 groupby 和 shift