Pandas Groupby 多列 - 前 N 个

Posted

技术标签:

【中文标题】Pandas Groupby 多列 - 前 N 个【英文标题】:Pandas Groupby Multiple Columns - Top N 【发布时间】:2019-07-02 22:17:24 【问题描述】:

我有一个有趣的!而且我试图找到一个重复的问题,但没有成功...

我的数据框包含 2013-2016 年的所有美国和地区,并具有多个属性。

>>> df.head(2)
     state  enrollees  utilizing  enrol_age65  util_age65  year
1  Alabama     637247     635431       473376      474334  2013
2   Alaska      30486      28514        21721       20457  2013

>>> df.tail(2)
     state               enrollees  utilizing  enrol_age65  util_age65  year
214  Puerto Rico          581861     579514       453181      450150  2016
215  U.S. Territories      24329      16979        22608       15921  2016

我想按年份和州分组,并显示每年排名前 3 位的州(按“注册者”或“使用” - 无关紧要)。

期望的输出:

                                       enrollees  utilizing
year state                                                 
2013 California                          3933310    3823455
     New York                            3133980    3002948
     Florida                             2984799    2847574
...
2016 California                          4516216    4365896
     Florida                             4186823    3984756
     New York                            4009829    3874682

到目前为止,我已经尝试了以下方法:

df.groupby(['year','state'])['enrollees','utilizing'].sum().head(3)

仅产生 GroupBy 对象中的前 3 行:

                 enrollees  utilizing
year state                           
2013 Alabama        637247     635431
     Alaska          30486      28514
     Arizona        707683     683273

我也试过一个 lambda 函数:

df.groupby(['year','state'])['enrollees','utilizing']\
  .apply(lambda x: np.sum(x)).nlargest(3, 'enrollees')

在 GroupBy 对象中产生绝对最大的 3:

                 enrollees  utilizing
year state                           
2016 California    4516216    4365896
2015 California    4324304    4191704
2014 California    4133532    4011208

我认为这可能与 GroupBy 对象的索引有关,但我不确定...任何指导将不胜感激!

【问题讨论】:

添加.sort_values(by='enrollees', ascending=False) 之前 .head(3) 这不会保持 GroupBy 对象按年份排序。它将返回 所有年的前 3 个州(恰好是 2016 年、2015 年和 2014 年的加利福尼亚州)。 尝试使用 nlargest(3, ['year', 'enrollees'])?另见***.com/questions/47703606/… @DouglasPearson 传递类似 ['year','enrollees'] 的列表不起作用 - 我也尝试过 :( 我认为必须在未用于索引的项目上调用 nlargest groupby。至于链接,该解决方案仅适用于至少有 3 行的组。我的组只有 1 行(每年一个州)。由于我按两列分组,因此它也变得不稳定。跨度> 为什么df.groupby(['State','Year'])['enrollees'].nlargest(3) 似乎不起作用?? 【参考方案1】:

好吧,你可以做一些不那么漂亮的事情。

首先使用set()获取唯一年份列表:

years_list = list(set(df.year))

创建一个虚拟数据框和一个我过去制作的 concat 函数:

def concatenate_loop_dfs(df_temp, df_full, axis=0):
    """
    to avoid retyping the same line of code for every df.
    the parameters should be the temporary df created at each loop and the concatenated DF that will contain all
    values which must first be initialized (outside the loop) as df_name = pd.DataFrame(). """ 

if df_full.empty:
    df_full = df_temp
else:
    df_full = pd.concat([df_full, df_temp], axis=axis)

return df_full

创建虚拟最终df

df_final = pd.DataFrame()

现在您将循环每年并连接到新的 DF:

for year in years_list:
    # The query function does a search for where
    # the @year means the external variable, in this case the input from loop
    # then you'll have a temporary DF with only the year and sorting and getting top3
    df2 = df.query("year == @year")

    df_temp = df2.groupby(['year','state'])['enrollees','utilizing'].sum().sort_values(by="enrollees", ascending=False).head(3)
    # finally you'll call our function that will keep concating the tmp DFs
    df_final = concatenate_loop_dfs(df_temp, df_final)

完成了。

print(df_final)

【讨论】:

我已经尝试过您的解决方案,但是“年”不是 groupby 对象的列 - 它是一个索引。 years_list = list(set(df2.year)) 将不起作用。不过我会尝试解决它。​​ 但它是original df中的一列,不是吗?只需将df2.year 替换为df.year。甚至df['year'] 甚至df2.index 嗯,顺便说一句,因为它是一个索引,所以循环将无法正常工作,我将对其进行编辑以适合您,请稍等。完成。 你错了!!关于它不起作用:)我遵循了您的代码,它为我提供了正确的输出:)谢谢!虽然我希望 pandas 中有一个内联命令/函数来帮助解决这个问题...... 很高兴为您提供帮助:)【参考方案2】:

然后您需要对 GroupBy 对象.sort_values('enrollees), ascending=False进行排序

【讨论】:

我也试过了......但是,它在没有保持年份索引完整性的情况下进行排序。它只会按降序列出总和最高的州,而不按年份排序。

以上是关于Pandas Groupby 多列 - 前 N 个的主要内容,如果未能解决你的问题,请参考以下文章

Pandas Groupby 独特的多列

pandas pivot 或 groupby 多列和控制列

使用多列的 Pandas groupby 函数

pandas groupby 聚合具有多列的自定义函数

t 测试 groupby pandas 之后的多列

Pandas 一次缩放多列并使用 groupby() 进行逆变换