【问题标题】:Pandas: Replace NaN with Average by Multi Level IndexPandas:通过多级索引将 NaN 替换为平均值
【发布时间】:2019-03-13 22:55:24
【问题描述】:

我有两个数据框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 应填充 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 将由带有 * 的值填充。

我尝试使用groupby().mean() 创建一个新的DataFrame,然后使用.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)

【问题讨论】:

  • 预期输出是什么?什么是数字而不是 NaN?
  • 预期的输出是 df_countries 数据框的 NaN 由每个集群和年份的平均非 NaN 值填充。
  • 嗨,我不清楚你想如何取平均值。在您的示例中,由于year_id=2016 只有一个country_id=1,因此无法取平均值。我知道这只是一个例子。但我认为也许你应该举一个可以找到平均值的例子。还是我不明白什么?
  • @nunoapedro - 我也不清楚,所以请问样本数据的平均值是多少?替换第一个NaN,第二个和类似的数字是多少?看来你的数据不是minimal, complete, and verifiable example
  • 嘿 @mortysporty 和 jezrael,问题中并不清楚,但我已经更新了表格。数据完整,每个country_id都有一个cluster_id在1到4之间,共有50个国家,每个国家都有2015年到2018年的数据。我只举了一个例子。

标签: python pandas dataframe


【解决方案1】:

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

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')

【讨论】:

  • 填充值必须是每个集群和年份的平均值,类似于avg_cluster 打印的内容。不过,我会尝试转置 DataFrame。
  • s 是每个集群和年份的平均值,请查看 axis=1 参数。
  • 谢谢,没错,它确实按集群和年份计算平均值。但是,当我打印它时,它是 col1、col2、col3 和 col4 的平均值——我需要每列的平均值(但按集群、年份),并将其应用于国家、年份 NaN 值
【解决方案2】:

知道了。

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

忘记使用正确的索引保留答案...通过此更改,它可以工作。 但是,如果有人有更 Pythonic 的方式来做到这一点,请添加您的答案!

【讨论】:

    猜你喜欢
    • 2016-01-08
    • 2013-09-12
    • 2013-04-01
    • 2016-03-18
    • 2019-03-21
    • 2020-07-14
    • 2020-01-16
    相关资源
    最近更新 更多