【问题标题】:Python pandas - Aggregate values in separate columnsPython pandas - 在单独的列中聚合值
【发布时间】:2021-03-09 11:45:06
【问题描述】:

我是 Python 新手,想知道是否有人可以帮助我完成以下任务。

我有以下数据框 df,其中包含以下列:

  • 主要 ID
  • 次要 ID
  • 实体类型
  • 价值

每个主要实体(实体类型:A)可能包含一些次要实体(实体类型;X 或 Y)。对于实体类型 A,主 ID 与辅助 ID 相同。此外,每个主要实体和每个次要实体都有一个值。

在“次要 id X 值总和”和“次要 id Y 值总和”列中,我希望获得与每个主要实体相对应的次要实体(X 和 Y)的合计值。聚合值应该在主要实体的行中。

所以,我最初的 df 是这样的:

Primary ID Secondary ID Entity type Value
0109 0109 A 200
0109 A234 X 100
0109 A234 X 50
9996 9996 A 400
9996 AAGT X 120
9996 AABG X 30
9996 0082 Y 50
A765 A765 A 50

我只想添加 2 列,而不更改初始数据框的格式:

Primary ID Secondary ID Entity type Value Sum of values Secondary id X Sum of values Secondary id Y
0109 0109 A 200 150 0
0109 A234 X 100 0 0
0109 A234 X 50 0 0
9996 9996 A 400 150 50
9996 AAGT X 120 0 0
9996 AABG X 30 0 0
9996 0082 Y 50 0 0
A765 A765 A 50 0 0

谢谢!

【问题讨论】:

    标签: python pandas dataframe sum aggregate


    【解决方案1】:

    尝试使用以下方法创建字典:

    (df.groupby(['Primary ID', 'Entity type'])['Value']      
            .sum()    
            .unstack(-1)                    
            .fillna(0).reset_index()                      
            ) 
    

    Entity type Primary ID  A   X       Y
    0           0109    200.0   150.0   0.0
    1           9996    400.0   150.0   50.0
    2           A765    50.0    0.0     0.0
    

    上面的数据可以转换成dict,然后就可以map了。

    完整解决方案:

    map_df = (df.groupby(['Primary ID', 'Entity type'])['Value']      
            .sum()    
            .unstack(-1)                    
            .fillna(0).reset_index()                      
            ).drop(['A'], axis=1).set_index('Primary ID')
    

    df.set_index('Primary ID', inplace=True)
    df.loc[df['Entity type'].eq('A'),['new_x', 'new_y']] = map_df.values
    

    df:

    Secondary ID Entity type Value new_x new_y
    Primary ID
    0109 0109 A 200 150.0 0.0
    0109 A234 X 100 0.0 0.0
    0109 A234 X 50 0.0 0.0
    9996 9996 A 400 150.0 50.0
    9996 AAGT X 120 0.0 0.0
    9996 AABG X 30 0.0 0.0
    9996 0082 Y 50 0.0 0.0
    A765 A765 A 50 0.0 0.0

    【讨论】:

      【解决方案2】:

      首先使用第一个解决方案,将Values 替换为Series.where 的缺失值,然后使用GroupBy.transform 的新列,最后在DataFrame.mask 中用0 替换重复项:

      cols = ['Sum of values Secondary id X','Sum of values Secondary id Y']
      df[cols] = (df.assign(x = df['Value'].where(df['Entity type'].eq('X')),
                            y = df['Value'].where(df['Entity type'].eq('Y')))
                    .groupby('Primary ID')[['x','y']]
                    .transform('sum')
                    .mask(df['Primary ID'].duplicated(), 0)
                    .astype(int))
      print (df)
        Primary ID Secondary ID Entity type  Value  Sum of values Secondary id X  \
      0       0109         0109           A    200                           150   
      1       0109         A234           X    100                             0   
      2       0109         A234           X     50                             0   
      3       9996         9996           A    400                           150   
      4       9996         AAGT           X    120                             0   
      5       9996         AABG           X     30                             0   
      6       9996         0082           Y     50                             0   
      7       A765         A765           A     50                             0   
      
         Sum of values Secondary id Y  
      0                             0  
      1                             0  
      2                             0  
      3                            50  
      4                             0  
      5                             0  
      6                             0  
      7                             0 
      

      如果需要新列的所有值,请使用 DataFrame.pivot_tableDataFrame.join

      df1 = (df.pivot_table(index='Primary ID', 
                          columns='Entity type', 
                          values='Value', 
                          aggfunc='sum', fill_value=0)
               .add_prefix('Sum of values Secondary id '))
      
      
      df = df.join(df1, on='Primary ID')
      df.loc[df['Primary ID'].duplicated(), df1.columns] = 0
      print (df)
        Primary ID Secondary ID Entity type  Value  Sum of values Secondary id A  \
      0       0109         0109           A    200                           200   
      1       0109         A234           X    100                             0   
      2       0109         A234           X     50                             0   
      3       9996         9996           A    400                           400   
      4       9996         AAGT           X    120                             0   
      5       9996         AABG           X     30                             0   
      6       9996         0082           Y     50                             0   
      7       A765         A765           A     50                            50   
      
         Sum of values Secondary id X  Sum of values Secondary id Y  
      0                           150                             0  
      1                             0                             0  
      2                             0                             0  
      3                           150                            50  
      4                             0                             0  
      5                             0                             0  
      6                             0                             0  
      7                             0                             0  
      

      【讨论】:

      • @Pygirl - 是的,我想同样的问题 - 有人认为我的第一个解决方案很糟糕,所以被否决了。
      猜你喜欢
      • 2017-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 2021-12-05
      • 2019-07-06
      • 2017-12-25
      相关资源
      最近更新 更多