pandas groupby суммирует различия между двумя столбцами и получает среднее значение для каждой группы - PullRequest
1 голос
/ 19 июня 2019

У меня есть следующие df,

year    code    col1   col2
2019    1       2      3
2019    1       3      5
2019    1       2      4
2018    2       1      4
2018    2       2      6

Я хочу groupby df на year и code, затем сложить различия между col2 и col1, а затем усреднить сумму по размеру группы;

df.apply(lambda row: (row['col_2'] - row['col_1']).mean(level=[0, 1]).reset_index(name='avg_num')

этот код, по-видимому, вычисляет среднее значение различий, а не суммирует различия и делит их на размер группы, так как это исправить?

year    code    col1   col2    avg_num
2019    1       2      3       1.66
2019    1       3      5       1.66
2019    1       2      4       1.66
2018    2       1      4       3.5
2018    2       2      6       3.5

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Используйте GroupBy.transform для нового столбца, заполненного совокупными значениями:

df['avg_num'] = (df.assign(avg_num=df.col2 - df.col1)
                   .groupby(['year', 'code'])['avg_num']
                   .transform('mean').round(2))
print (df)
   year  code  col1  col2  avg_num
0  2019     1     2     3     1.67
1  2019     1     3     5     1.67
2  2019     1     2     4     1.67
3  2018     2     1     4     3.50
4  2018     2     2     6     3.50

Другое решение без assign, но необходимо передать столбцы в groupby, такие как df['year'] и df['code']:

df['avg_num'] = ((df['col2'] - df['col1']).groupby([df['year'], df['code']])
                                          .transform('mean').round(2))
print (df)
   year  code  col1  col2  avg_num
0  2019     1     2     3     1.67
1  2019     1     3     5     1.67
2  2019     1     2     4     1.67
3  2018     2     1     4     3.50
4  2018     2     2     6     3.50
1 голос
/ 19 июня 2019
data = df.groupby(['year','code']).apply(lambda x: sum(list(abs(x.col2 - x.col1))) / len(list(abs(x.col2 - x.col1)))).reset_index().rename({0:'avg_num'},axis=1)

df.merge(data, on='year').drop('code_y', axis=1).rename({'code_x':'code'}, axis=1)

выход

   year  code  col1  col2   avg_num
0  2019     1     2     3  1.666667
1  2019     1     3     5  1.666667
2  2019     1     2     4  1.666667
3  2018     2     1     4  3.500000
4  2018     2     2     6  3.500000
1 голос
/ 19 июня 2019

Мы можем создать промежуточную таблицу для хранения агрегированных значений и затем присоединить ее к исходному кадру данных.

aggs = df.assign(avg_num=df.col2 - df.col1) \
         .groupby(['year', 'code'], as_index=False)['avg_num'].mean().round(2)

print(aggs)

   year  code  avg_num
0  2018     2   3.50
1  2019     1   1.67

df.merge(aggs, how='inner', left_on=['year', 'code'], right_on=['year', 'code'])

   year  code  col1  col2  avg_num
0  2019     1     2     3   1.67
1  2019     1     3     5   1.67
2  2019     1     2     4   1.67
3  2018     2     1     4   3.50
4  2018     2     2     6   3.50
...