根据自定义函数聚合数据框中的多个列

时间:2018-03-14 08:04:39

标签: python pandas dataframe group-by summary

下午全部,

我一直试图解决这个问题,任何帮助都会受到赞赏。

这是我的数据框:

Channel state       rfq_qty
A        Done       10
B        Tied Done  10
C        Done       10
C        Done       10
C        Done       10
C        Tied Done  10
B        Done       10
B        Done       10
  

我想:

     
      
  1. 按渠道分组,然后是州
  2.   
  3. 汇总每个频道的rfq_qty
  4.   
  5. 计算状态中每个'完成'字符串的出现次数('完成'与'绑定完成'相同,即其中包含'完成'的任何内容)
  6.   
  7. 将频道rfq_qty显示为rfq_qty(80)总数的百分比
  8.   
Channel state   rfq_qty Percentage
A         1       10    0.125
B         3       30    0.375
C         4       40    0.5
  

我尝试了以下内容:

df_Done = df[
                (
                    df['state']=='Done'
                ) 
                | 
                (
                    df['state'] == 'Tied Done'
                )
            ][['Channel','state','rfq_qty']]

df_Done['Percentage_Qty']= df_Done['rfq_qty']/df_Done['rfq_qty'].sum()
df_Done['Done_Trades']= df_Done['state'].count()

display(
        df_Done[
                (df_Done['Channel'] != 0)
               ].groupby(['Channel'])['Channel','Count of Done','rfq_qty','Percentage_Qty'].sum().sort_values(['rfq_qty'], ascending=False)
       )
  

工作但看起来很复杂。有什么改进吗?

2 个答案:

答案 0 :(得分:1)

我认为你可以使用:

  • 首先按isinloc
  • 过滤
  • groupby并按agg汇总新列名称和函数的元组
  • divPercentage
  • 除以sum
  • 必要时sort_values rfq_qty
df_Done = df.loc[df['state'].isin(['Done', 'Tied Done']), ['Channel','state','rfq_qty']]

#if want filter all values contains Done
#df_Done = df[df['state'].str.contains('Done')]

#if necessary filter out Channel == 0
#mask = (df['Channel'] != 0) & df['state'].isin(['Done', 'Tied Done'])
#df_Done = df.loc[mask, ['Channel','state','rfq_qty']]

d = {('rfq_qty', 'sum'), ('Done_Trades','size')}
df = df_Done.groupby('Channel')['rfq_qty'].agg(d).reset_index()
df['Percentage'] = df['rfq_qty'].div(df['rfq_qty'].sum())
df = df.sort_values('rfq_qty')
print (df)
  Channel  Done_Trades  rfq_qty  Percentage
0       A            1       10       0.125
1       B            3       30       0.375
2       C            4       40       0.500

答案 1 :(得分:0)

一种方法是使用单个df.groupby.agg并重命名列:

import pandas as pd

df = pd.DataFrame({'Channel': ['A', 'B', 'C', 'C', 'C', 'C', 'B', 'B'],
                   'state': ['Done', 'Tied Done', 'Done', 'Done', 'Done', 'Tied Done', 'Done', 'Done'],
                   'rfq_qty': [10, 10, 10, 10, 10, 10, 10, 10]})

agg_funcs = {'state': lambda x: x[x.str.contains('Done')].count(),
             'rfq_qty': ['sum', lambda x: x.sum() / df['rfq_qty'].sum()]}

res = df.groupby('Channel').agg(agg_funcs).reset_index()
res.columns = ['Channel', 'state', 'rfq_qty', 'Percentage']

#   Channel  state  rfq_qty  Percentage
# 0       A      1       10       0.125
# 1       B      3       30       0.375
# 2       C      4       40       0.500

这不是最有效的方式,因为它依赖于非向量化聚合,但如果它符合您的用例,则可能是一个不错的选择。