22

I look most of the previously asked questions but was not able to find answer for my question:

I have following dataframe

           id   year month score num_attempts
0      483625  2010    01   50      1
1      967799  2009    03   50      1
2      213473  2005    09  100      1
3      498110  2010    12   60      1
5      187243  2010    01  100      1
6      508311  2005    10   15      1
7      486688  2005    10   50      1
8      212550  2005    10  500      1
10     136701  2005    09   25      1
11     471651  2010    01   50      1

I want to get the following dataframe

year month sum_score sum_num_attempts
2009    03   50           1
2005    09  125           2
2010    12   60           1
2010    01  200           2
2005    10  565           3

Here is what I tried:

sum_df = df.groupby(by=['year','month'])['score'].sum()

But this doesn't look efficient and correct. If I have more than one column need to be aggregate this seems like a very expensive call. for example if I have another column num_attempts and just want to sum by year month as score.

cottontail
  • 10,268
  • 18
  • 50
  • 51
add-semi-colons
  • 18,094
  • 55
  • 145
  • 232

2 Answers2

24

This should be an efficient way:

sum_df = df.groupby(['year','month']).agg({'score': 'sum', 'num_attempts': 'sum'})
Dennis Golomazov
  • 16,269
  • 5
  • 73
  • 81
0

An alternative way is to call groupby.sum on multiple columns and add prefix afterwards. This produces the desired column labels in the OP.

sum_df = df.groupby(['year', 'month'])[['score', 'num_attempts']].sum().add_prefix('sum_').reset_index()

or use named aggregation from the beginning

sum_df = df.groupby(['year', 'month'], as_index=False).agg(sum_score=('score', 'sum'), sum_num_attempts=('num_attempts', 'sum'))

Both produce the following frame:

res

cottontail
  • 10,268
  • 18
  • 50
  • 51