【问题标题】:Pandas Groupby: Aggregations on the same column but totals based on two different critera / dataframesPandas Groupby:同一列上的聚合,但总计基于两个不同的标准/数据框
【发布时间】:2018-12-16 21:34:59
【问题描述】:

我的数据框:

display_name    security_type1  currency_str     state
         A            GOVT           USD         Done
         B            CORP           NZD         Passed
         B            CORP           USD         Done
         C            CORP           EUR         Done
         C            CORP           EUR         Traded Away
         C            CORP           GBP         Done
         C            CORP           GBP         Done
         C            CORP           USD         Done

我想要的结果是:

一个。分组display_namesecurity_type1currency_str

b.然后计算column state包含Done的行数并更新列Done_RFQ

c。显示每个display_namesecurity_type1currency_str组合的总行数并更新列Total_RFQ

d。最后显示完成占总数的百分比,即Done_Pct = Done_RFQ / Total_RFQ

display_name    security_type1  currency_str   Done_RFQ Total_RFQ Done_Pct
A               GOVT             USD           1           1      100%
B               CORP             USD           1           2      50%
C               CORP             EUR           1           5      20%
C               CORP             GBP           2           5      40%
C               CORP             USD           1           5      20%

我的代码除了Total_RFQDone_Pct 之外都可以工作

d = [('Done_RFQ', 'size')]
df_Done_Client = df[
                    df['state'].str.contains('Done')
                ][['display_name','security_type1','currency_str','state']].copy()

df_Done_Client =    
    df_Done_Client.groupby(['display_name','security_type1','currency_str'])['state'].agg(d).reset_index()
    # Sum of all Done RFQ's per display_name
    Sum_of_Done_For_Month = df_Done_Client.groupby('display_name')['Done_RFQ'].transform('sum')
    df_Done_Client['Total_Done_RFQ'] = Sum_of_Done_For_Month
    df_Done_Client['Done_Pct'] = df_Done_Client['Done_RFQ_For_Month'].div(Sum_of_Done_For_Month).round(5)
    display(df_Done_Client)

我不清楚如何计算这个总数,因为它需要来自另一个数据框,即相同的字段但没有“完成”标准。

df_All_Client = df[['display_name','security_type1','currency_str','state']].copy()

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    我认为需要Total_RFQ 列和size - 总计数和Done_RFQ 按布尔掩码计数 - 与Trues 的Donesum 比较:

    d = [('Total_RFQ', 'size'), ('Done_RFQ', lambda x: x.eq('Done').sum())]
    df=df.groupby(['display_name','security_type1','currency_str'])['state'].agg(d).reset_index()
    df['Done_Pct'] = df['Done_RFQ'] / df['Total_RFQ'] * 100
    print (df)
      display_name security_type1 currency_str  Total_RFQ  Done_RFQ  Done_Pct
    0            A           GOVT          USD          1         1     100.0
    1            B           CORP          NZD          1         0       0.0
    2            B           CORP          USD          1         1     100.0
    3            C           CORP          EUR          2         1      50.0
    4            C           CORP          GBP          2         2     100.0
    5            C           CORP          USD          1         1     100.0
    

    如果需要检查子字符串:

    d = [('Total_RFQ', 'size'), ('Done_RFQ', lambda x: x.str.contains('Done').sum())]
    df=df.groupby(['display_name','security_type1','currency_str'])['state'].agg(d).reset_index()
    df['Done_Pct'] = df['Done_RFQ'] / df['Total_RFQ'] * 100
    print (df)
      display_name security_type1 currency_str  Total_RFQ  Done_RFQ  Done_Pct
    0            A           GOVT          USD          1         1     100.0
    1            B           CORP          NZD          1         0       0.0
    2            B           CORP          USD          1         1     100.0
    3            C           CORP          EUR          2         1      50.0
    4            C           CORP          GBP          2         2     100.0
    5            C           CORP          USD          1         1     100.0
    

    【讨论】:

    • 有效!! state 列可以包含我们想要包含的“Done”和“Tied Done”。看来 .contains 方法不可用。可以将 x.eq 更新为什么以包含任何带有“完成”的字符串?
    • @PeterLucas - 这取决于需要什么,如果需要检查子字符串更好的是x.str.contains('Done').sum(),如果需要检查字符串x.eq('Done').sum()
    【解决方案2】:

    这是一种方法。类似于@jezrael 的解决方案,但保留您的逻辑来检查子字符串Done 并过滤Done_RFQ > 0

    另外,我相信你需要2次groupby计算才能得到你想要的结果,即Total_RFQ是由display_name计算的。

    # function to calcuate Done_RFQ
    d = {'Done_RFQ': lambda x: x.str.contains('Done', na=False, regex=False).sum()}
    
    # apply 2 groupby calculations
    df['Total_RFQ'] = df.groupby('display_name')['display_name'].transform('size')
    
    group_cols = ['display_name', 'security_type1', 'currency_str', 'Total_RFQ']
    res = df.groupby(group_cols)['state'].agg(d).reset_index()
    
    # calculate Done_Pct
    res['Done_Pct'] = res['Done_RFQ'] / res['Total_RFQ']
    
    # filter for Done_RFQ > 0
    res = res[res['Done_RFQ'] > 0]
    
    print(res)
    
      display_name security_type1 currency_str  Total_RFQ  Done_RFQ  Done_Pct
    0            A           GOVT          USD          1         1       1.0
    2            B           CORP          USD          2         1       0.5
    3            C           CORP          EUR          5         1       0.2
    4            C           CORP          GBP          5         2       0.4
    5            C           CORP          USD          5         1       0.2
    

    【讨论】:

      猜你喜欢
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      • 2015-08-20
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      相关资源
      最近更新 更多