熊猫:用多级指数将NaN替换为平均值

时间:2019-03-13 12:08:38

标签: python pandas dataframe

我有两个数据帧df_country_clusterdf_countries,具有以下结构(按顺序):

            cluster_id
country_id
1                    4
2                    4
...                  ...

                     col1   col2   col3   col4
country_id  year_id
1           2015     0.1    0.2    0.3    0.1
1           2016     0.4    NaN    0.1    0.8
1           2017     0.7    0.2    0.6    NaN
1           2018     0.9    0.4    0.7    0.2  
2           2015     0.5    0.6    NaN    0.3 
2           2016     0.3    0.7    0.2    0.5 
2           2017     0.2    0.9    0.3    0.5 
2           2018     0.1    0.2    0.1    0.9 
...         ...      ...    ...    ...    ...

我的目标是用每个群集和年份的平均非NaN值填充NaN值。这意味着,例如,country_id 1,year_id 2016,col2中的NaN应该用col2在2016年的有效值的平均值和所有cluster_id为4(在这种情况下)的国家/地区。

在上面的示例中,我们将以这种方式获得cluster_id 4的平均值:

                     col1   col2   col3   col4
cluster_id  year_id
4           2015     0.3    0.4    *0.3   0.2
4           2016     0.4    *0.7   0.2    0.6
4           2017     0.4    0.6    0.4    *0.5
4           2018     0.5    0.3    0.4    0.6

因此,NaN每列将用*填充值。

我尝试用DataFrame创建一个新的groupby().mean(),然后使用.fillna,但没有成功。其他SO问题like this仅讨论单索引问题。

这是我的方法:

    cols = ['col1','col2','col3','col4']
    original_index = df_countries.index

    df_countries = df_countries.join(df_country_cluster,on='country_id')
    df_countries = df_countries.reset_index().set_index(['cluster_id','year_id'])
    avg_cluster = df_countries.groupby(['cluster_id','year_id']).mean()
    avg_cluster = avg_cluster[cols]

    for col in cols:
        df_countries[col].fillna(avg_cluster[col],inplace=True)

    df_countries.reset_index().set_index(original_index)

2 个答案:

答案 0 :(得分:0)

我不确定我是否理解正确。但是您的方法看起来不错。所以我们从

开始
df = df_countries.join(df_country_cluster, on='country_id')
df = df.reset_index().set_index(['cluster_id','year_id'])

您说填充值是每组的平均值:

s = df[['col1', 'col2', 'col3', 'col4']].mean(axis=1)

如果我们转置DataFrame,我们可以放在一起

df = df.T.fillna(value=s).T

最后,我们放弃了不需要的东西

df = df.reset_index().drop(columns='cluster_id').set_index('country_id', 'year_id')

答案 1 :(得分:0)

知道了。

df_countries = df_countries.reset_index().set_index(original_index)

忘记用正确的索引来保留答案...通过此更改,它可以工作。 但是,如果有人有更Python化的方法,请添加答案!