Панды, группируют фрейм данных и нормализуют значения в каждой группе

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть csv-файл с разными группами, идентифицируемыми идентификатором, что-то вроде:

 ID,X
aaa,3
aaa,5
aaa,4
bbb,50
bbb,54
bbb,52
 

Мне нужно:

  • вычислите среднее значение x в каждой группе;
  • разделите каждое значение x на среднее значение x для этой конкретной группы.

Итак, в моем примере выше среднее значение в группе ‘aaa’ равно 4, а в ‘bbb’ — 52. Мне нужно получить новый фрейм данных с третьим столбцом, где в каждой строке у меня есть исходное значение x, деленное на среднее значение по группе:

 ID,X,x/group_mean
aaa,3,3/4
aaa,5,5/4
aaa,4,4/4
bbb,50,50/52
bbb,54,54/52
bbb,52,52/52
 

Я могу сгруппировать фрейм данных и вычислить среднее значение каждой группы по:

     df_data = pd.read_csv('test.csv', index_col=0)
    df_grouped = df_data.groupby('ID')
    for group_name, group_content in df_grouped:
        mean_x_group = group_content['x'].mean()
        print(f'mean = {mean_x_group}')
 

но как мне добавить третий столбец?

Ответ №1:

Используйте Groupby.transform :

 In [1874]: df['mean']  = df.groupby('ID').transform('mean')

In [1879]: df['newcol'] = df.X.div(df['mean'])

In [1880]: df
Out[1880]: 
    ID   X  mean    newcol
0  aaa   3     4  0.750000
1  aaa   5     4  1.250000
2  aaa   4     4  1.000000
3  bbb  50    52  0.961538
4  bbb  54    52  1.038462
5  bbb  52    52  1.000000
 

Комментарии:

1. Хорошо, что об этом напоминают .tranform в groupby. Я часто просто использую .agg только для того, чтобы найти способ транслировать среднее значение для всех строк. Для этого.

Ответ №2:

Идея заключается в аккуратном однострочном:

df['new_column'] = df.apply(lambda row: row.X/df.loc[df.ID==row.ID, 'X'].mean(), axis=1)

Комментарии:

1. Хотя это не очень аккуратно!!

2. Это аккуратно в том смысле, что, так сказать, ближе к разговорному языку. «Для каждой строки возьмите X и разделите его на среднее значение». Независимо от аккуратности или нет, я думаю, что все же полезно использовать больше подходов к проблеме, чтобы вдохновить другие идеи и для других проблем.

3. Конечно, я согласен с этим.

Ответ №3:

Один линейный код для этого

 # divide X with mean of X group by ID

df['group_mean'] = df.X / df.groupby('ID').transform('mean').X