在熊猫群中显示较低级别,由

问题描述 投票:0回答:1

我对数据中的每组数据进行汇总统计,同时使用多个分组标准。的数据。

import pandas as pd
d = {'Fruit': ['Apple', 'Apple','Apple','Orange','Orange'], 
     'City': ['Rome', 'Rome', 'London', 'London','London' ],
     'Value': [1, 2, 3, 4, 5 ]}
df = pd.DataFrame(data=d)
print(df)

    Fruit    City  Value 
0  Apple   Rome    1    
1  Apple   Rome    2    
2  Apple   London  3    
3  Orange  London  4    
4  Orange  London  5    

"groupby "命令只返回最高层的和。

keys=['Fruit','City']

df.groupby(keys).agg(Total_Value=('Value', 'sum'))  

               Total_Value
Fruit  City               
Apple  London  3          
       Rome    3          
Orange London  9          

我希望将和函数也应用到较低级别。最好是将所有级别的结果显示在同一个表格中。

               Total_Value
Fruit  City
               15
Apple          6
Orange         9
       London  12
       Rome    3
Apple  London  3          
Apple  Rome    3          
Orange London  9 

有什么简单的方法可以生成这样一个表格吗?也许可以使用多索引函数来实现这一目的,但我不确定应该如何应用。

非常感谢

PS:在例子中,我使用了 "sum "函数。计算低级别的和相对容易。我正在寻找一个通用答案,它适用于所有函数,而不仅仅是和。(例如,平均数函数,或lambda函数等)

PS2: 类似下面的方法也可以。

               Total_Value Level
Fruit  City               
                        15 0
       Rome              3 1
       London           12 1
Apple                    6 1
Orange                   9 1
Apple  Rome              3 2
       London            3 2
Orange London            9 2

在这种情况下,"London "的 "Total_Value "就很清楚了。不需要检查行的顺序。

python pandas pandas-groupby
1个回答
1
投票

你可以创建所有可能的组合 keys,然后将其转换为dicts来替换相同的值,这里是空字符串,并传递给 DataFrame.assign那么 concat 汇总 sum 或任何其他功能,如需要。

keys = ['Fruit','City']

#https://stackoverflow.com/a/5898031
from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

dfs = [df.assign(**dict.fromkeys(x, '')) for x in all_subsets(keys)]

#swapped order of list of DataFrames
df1 = (pd.concat(dfs[::-1], sort=False)
         .groupby(keys, sort=False)
         .agg(Total_Value=('Value', 'sum')))
print (df1)
               Total_Value
Fruit  City               
                        15
Apple                    6
Orange                   9
       Rome              3
       London           12
Apple  Rome              3
       London            3
Orange London            9

备用功能。

keys = ['Fruit','City']

#swapped order in range
from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(len(ss)+1, -1, -1)))

dfs = [df.assign(**dict.fromkeys(x, '')) for x in all_subsets(keys)]

df = pd.concat(dfs, sort=False).groupby(keys, sort=False).agg(Total_Value=('Value', 'sum'))  
print (df)
               Total_Value
Fruit  City               
                        15
       Rome              3
       London           12
Apple                    6
Orange                   9
Apple  Rome              3
       London            3
Orange London            9

EDIT:

d = {'Fruit': ['Apple', 'Apple','Apple','Orange','Orange'], 
     'City': ['Rome', 'Rome', 'London', 'London','London' ],
     'Value': [1, 2, 3, 4, 5 ]}
df = pd.DataFrame(data=d)
print(df)

keys = ['Fruit','City']

#https://stackoverflow.com/a/5898031
from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

dfs = [df.assign(**dict.fromkeys(x, '')) for x in all_subsets(keys)]

#swapped order of list of DataFrames
df1 = (pd.concat(dfs[::-1], sort=False)
         .groupby(keys, sort=False)
         .agg(Total_Value=('Value', 'sum')))

最后,你可以将 MultiIndexDataFrameMultiIndex.to_frame,与不等于空的字符串相似,并使用 DataFrame.dot 诀窍如果没有列的值,则通过列的值创建系列 '':

df2 = df1.index.to_frame()
s = df2.ne('').dot(df2.columns + ' & ').str.strip('& ').replace('', 'All')
print (s)
Fruit   City  
                           All
Apple                    Fruit
Orange                   Fruit
        Rome              City
        London            City
Apple   Rome      Fruit & City
        London    Fruit & City
Orange  London    Fruit & City
dtype: object

df1['level'] = s
print (df1)
               Total_Value         level
Fruit  City                             
                        15           All
Apple                    6         Fruit
Orange                   9         Fruit
       Rome              3          City
       London           12          City
Apple  Rome              3  Fruit & City
       London            3  Fruit & City
Orange London            9  Fruit & City

0
投票

我会这样做。

import pandas as pd
d = {'Fruit': ['Apple', 'Apple','Apple','Orange','Orange'], 
     'City': ['Rome', 'Rome', 'London', 'London','London' ],
     'Value': [1, 2, 3, 4, 5 ]}
df = pd.DataFrame(data=d)

keys=['Fruit','City']

df_sum = df.groupby(keys).agg(Total_Value=('Value', 'sum')) 
df_sub = df_sum.sum(level=0).assign(City='Fruit SubTotal').set_index('City', append=True)
df_grand = df_sum.sum().to_frame().T.rename_axis('Fruit').rename(index={0:'Grand'}).assign(City='Total').set_index('City', append=True)

df_out = pd.concat([df_sum, df_sub, df_grand])
print(df_out)

产出:

                       Total_Value
Fruit  City                       
Apple  London                    3
       Rome                      3
Orange London                    9
Apple  Fruit SubTotal            6
Orange Fruit SubTotal            9
Grand  Total                    15
© www.soinside.com 2019 - 2024. All rights reserved.