在具有MultiIndex的熊猫数据框中,如何使用组均值有条件地填充缺失值?

问题描述 投票:2回答:3

设置:

# create a MultiIndex
dfx = pd.MultiIndex.from_product([
    list('ab'),
    list('cd'),
    list('xyz'),
], names=['idx1', 'idx2', 'idx3'])

# create a dataframe that fits the index
df = pd.DataFrame([None, .9, -.08, -2.11, 1.09, .38, None, None, -.37, -.86, 1.51, -.49], columns=['random_data'])
df.set_index(dfx, inplace=True)

输出:

                        random_data
idx1    idx2    idx3    
a       c       x       NaN
                y       0.90
                z      -0.08

        d       x      -2.11
                y       1.09
                z       0.38

b       c       x       NaN
                y       NaN
                z      -0.37

        d       x      -0.86
                y       1.51
                z      -0.49

在此索引层次结构中,我正在尝试完成以下任务:

  1. [在[idx1, idx2, idx3]中缺少值时,用NaN的组平均值填充[idx1, idx2]
  2. [在[idx1, idx2, idx3]中缺少多个值时,用NaN的组平均值填充[idx1]

我已经尝试过df.apply(lambda col: col.fillna(col.groupby(by='idx1').mean()))作为解决#2的方法,但是我无法使其正常工作。

UPDATE

好,所以我已经部分解决了这个问题,但是仍然对如何有条件地应用这些内容感到困惑:

对于案例1:

df.unstack().apply(lambda col: col.fillna(col.mean()), axis=1).stack()

我通过查看此内容验证了正确的值:

df.groupby(by=['idx1', 'idx2']).mean()

但是它也替换了我在情况2中试图以不同方式处理的缺失值。

同样适用于#2:

df.unstack().unstack().apply(lambda col: col.fillna(col.mean()), axis=1).stack().stack()

通过查看确认所替换的值是正确的>

df.groupby(by=['idx1']).mean()

但它也适用于情况#1,我不希望。

设置:#创建一个MultiIndex dfx = pd.MultiIndex.from_product([list('ab'),list('cd'),list('xyz'),],names = ['idx1','idx2' ,'idx3'])#创建一个适合索引df = pd的数据框。...

pandas multi-index fillna
3个回答
0
投票

我敢肯定有一种更优雅的方法,但是以下应该可以达到您想要的结果:


0
投票

IIUC,您可以尝试一下。获取级别meanidx1和级别[meanidx1]的idx2。 Fillna使用[idx1idx2]的平均值。接下来,使用mask通过NaNmean分配具有多于1个idx1的组的行

Sample `df`:
                random_data
idx1 idx2 idx3
a    c    x             NaN
          y           -0.09
          z           -0.01
     d    x           -1.30
          y           -0.11
          z            1.33
b    c    x             NaN
          y             NaN
          z            0.74
     d    x           -1.44
          y            0.50
          z           -0.61

df1_m = df.mean(level='idx1')
df12_m = df.mean(level=['idx1', 'idx2'])
m = df.isna().groupby(level=['idx1', 'idx2']).transform('sum').gt(1)

df_filled = df.fillna(df12_m).mask(m & df.isna(), df1_m)

Out[110]:
                random_data
idx1 idx2 idx3
a    c    x         -0.0500
          y         -0.0900
          z         -0.0100
     d    x         -1.3000
          y         -0.1100
          z          1.3300
b    c    x         -0.2025
          y         -0.2025
          z          0.7400
     d    x         -1.4400
          y          0.5000
          z         -0.6100

0
投票

好,解决了。

© www.soinside.com 2019 - 2024. All rights reserved.