【问题标题】:Arbitrary number of different groupby levels in one go一次性任意数量的不同groupby级别
【发布时间】:2020-02-12 13:20:01
【问题描述】:

有没有办法使用一些预先构建的 Pandas 函数一次性计算任意数量的不同 groupby 级别? 下面是一个包含两列的简单示例。

import pandas as pd

df1 = pd.DataFrame( { 
    "name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"], 
    "city" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"],  
    "dollars":[1, 1, 1, 1, 1, 1] })

group1 = df1.groupby("city").dollars.sum().reset_index()
group1['name']='All'

group2 = df1.groupby("name").dollars.sum().reset_index()
group2['city']='All'

group3 = df1.groupby(["name", "city"]).dollars.sum().reset_index()

total = df1.dollars.sum()
total_df=pd.DataFrame({ 
    "name" : ["All"], 
    "city" : ["All"],  
    "dollars": [total] })

all_groups = group3.append([group1, group2, total_df], sort=False)


    name    city    dollars
0   Alice   Seattle     1
1   Bob     Seattle     2
2   Mallory Portland    2
3   Mallory Seattle     1
0   All     Portland    2
1   All     Seattle     4
0   Alice   All         1
1   Bob     All         2
2   Mallory All         3
0   All     All         6

所以我带走了本。 T 示例并将其从 sum() 重建为 agg()。对我来说,下一步是构建一个选项来传递特定的 groupby 组合列表,以防不需要所有组合。

from itertools import combinations
import pandas as pd

df1 = pd.DataFrame( { 
    "name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"], 
    "city" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"],  
    "dollars":[1, 2, 6, 5, 3, 4],
    "qty":[2, 3, 4, 1, 5, 6] ,
    "id":[1, 1, 2, 2, 3, 3] 
})

col_gr = ['name', 'city']
agg_func={'dollars': ['sum', 'max', 'count'], 'qty': ['sum'], "id":['nunique']}

def multi_groupby(in_df, col_gr, agg_func, all_value="ALL"):
    tmp1 = pd.DataFrame({**{col: all_value for col in col_gr}}, index=[0])
    tmp2 = in_df.agg(agg_func)\
                .unstack()\
                .to_frame()\
                .transpose()\
                .dropna(axis=1)
    tmp2.columns = ['_'.join(col).strip() for col in tmp2.columns.values]
    total = tmp1.join(tmp2)

    for r in range(len(col_gr), 0, -1):
        for cols in combinations(col_gr, r):
            tmp_grp = in_df.groupby(by=list(cols))\
                .agg(agg_func)\
                .reset_index()\
                .assign(**{col: all_value for col in col_gr if col not in cols})
            tmp_grp.columns = ['_'.join(col).rstrip('_') for col in tmp_grp.columns.values]
            total = pd.concat([total]+[tmp_grp], axis=0, ignore_index=True)
    return total

multi_groupby(df1, col_gr, agg_func)


【问题讨论】:

  • Is there a way to compute arbitrary number of different groupby levels in one go with some pre-built Pandas function? 不,不存在。

标签: python pandas pandas-groupby


【解决方案1】:

假设您正在寻找一种通用方法来创建groupby 中的所有组合,您可以使用itertools.combinations

from itertools import combinations

col_gr = ['name', 'city']
col_sum = ['dollars']

all_groups = pd.concat( [ df1.groupby(by=list(cols))[col_sum].sum().reset_index()\
                             .assign(**{col:'all' for col in col_gr if col not in cols})
                         for r in range(len(col_gr), 0, -1) for cols in combinations(col_gr, r) ] 
                      + [ pd.DataFrame({**{col:'all' for col in col_gr}, 
                                        **{col: df1[col].sum() for col in col_sum},}, index=[0])], 
                        axis=0, ignore_index=True)
print (all_groups)

      name      city  dollars
0    Alice   Seattle        1
1      Bob   Seattle        2
2  Mallory  Portland        2
3  Mallory   Seattle        1
4    Alice       all        1
5      Bob       all        2
6  Mallory       all        3
7      all  Portland        2
8      all   Seattle        4
9      all       all        6

【讨论】:

  • 这是一个非常有趣的方法!我很难理解 ** 和 assign 的一些用法 - 你能告诉我这在 Python 中叫什么,以便我可以用谷歌搜索它吗?
  • @keg5038 ** 用于解压缩字典,assign 是 pandas 的一种方法,可以与解压缩字典一起使用。对于{**dict1, **dict2} 用于合并多个字典,有点像update
  • 太好了,非常感谢!我现在有一些谷歌搜索要做!
  • 我明白我提出问题的方式可能看起来我只是在寻找“所有组合”。我正在寻找一种方法来计算所需组合列表的结果(“所有组合”是可能的选项之一)。无论如何,你的例子对我帮助很大,谢谢!和keg5038一样,我学到了一些新东西:)
  • @GrinvydasKareiva 好的,我想如果你有组合列表,那么上面的方法有一些小的变化。如果您不确定,请告诉我,我可以编辑答案以适合您的评论:)
【解决方案2】:

这也是我一直在寻找的东西。以下是其他人编写的两种方法的链接,这些方法帮助我解决了这个问题。当然也会对其他拍摄感兴趣。

Link 1 Link 2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多