Pandas df: группа, корзина и среднее значение в разных столбцах? - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть данные, которые качественно выглядят как эта фиктивная таблица:

speed_observation, car_brand, traction_force
10, ford, 2
20, ford, 4
35, seat, 8
50, ford, 16
10, audi, 2
20, audi, 5
43, audi, 2
12, seat, 2.5
10, ford, 0.5
30, audi, 6
23, ford, 4
17, seat, 5.5
10, seat, 10
38, audi, 2
40, ford, 9
19, ford, 6.6
49, seat, 18
18, ford, 4 

Я хотел бы сгруппировать данные по маркам автомобилей и по каждой марке, чтобы объединить наблюдения скорости в диапазоны (например, [0,25 ] и [25,50]), а затем для каждой марки и корзины рассчитать среднее измеренное сцепление, получив что-то вроде:

speed_bin_upper_lim, car_brand, avrg_traction_force_in_speed_bin
25, audi, X1
50, audi, X2
25, ford, X3
50, ford, X4
25, seat, X5
50, seat, X6

Как мне это сделать? Он должен работать для произвольного числа уникальных car_brand классов, а пользователь должен указывать только количество скоростных бинов или диапазон бинов (например, n=3 или [0,25,50]). Я предполагаю, что pd.groupby и pd.cut сделают это, но я не нашел, как именно.


Ответ Куанга Хоанга работает очень хорошо, и если вы хотите расширить его, потому что вы хотите сгруппируйте еще один столбец, скажем, wheel_kind, и ваш фрейм данных будет выглядеть так:

speed_observation,car_brand,wheel_kind,traction_force
10, ford, winter, 2
20, ford, summer, 4
35, seat, summer, 8
50, ford, winter, 16
10, audi, summer, 2
20, audi, summer, 5
43, audi, summer, 2
12, seat, summer, 2.5
10, ford, summer, 0.5
30, audi, summer, 6
23, ford, summer, 4
17, seat, summer, 5.5
10, seat, summer, 10
38, audi, summer, 2
40, ford, summer, 9
19, ford, summer, 6.6
49, seat, summer, 18
18, ford, summer, 4

Затем просто добавьте столбец wheel_kind в предыдущее решение, точнее:

(df.groupby(['car_brand', `wheel_kind`, cuts])
   .traction_force.mean()
   .reset_index(name='avg_traction_force')
)

и после этого не забудьте сбросить NaN, потому что для ford и audi зимних колес нет:

df_grp.dropna(inplace=True)
df_grp.reset_index(drop=True, inplace=True) #just to reset the index

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

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

n = 25

blocks = (df.speed_observation.sub(1) // n).add(1).mul(n)
blocks = blocks.rename('speed_bin_upper_lim') 

(df.groupby([blocks, 'car_brand'])
   .traction_force.mean()
   .reset_index(name='avrg_traction_force_in_speed_bin'))

   speed_bin_upper_lim car_brand  avrg_traction_force_in_speed_bin
0                   25      audi                          3.500000
1                   25      ford                          3.516667
2                   25      seat                          6.000000
3                   50      audi                          3.333333
4                   50      ford                         12.500000
5                   50      seat                         13.000000

Сведения

print(blocks)
0     25
1     25
2     50
3     50
4     25
5     25
6     50
7     25
8     25
9     50
10    25
11    25
12    25
13    50
14    50
15    25
16    50
17    25
Name: speed_bin_upper_lim, dtype: int64
1 голос
/ 02 апреля 2020

Вы можете просто вырезать speed_observation с желаемыми лотками и сгруппировать следующим образом:

cuts = pd.cut(df['speed_observation'], [0,25,50])

(df.groupby(['car_brand', cuts])
   .traction_force.mean()
   .reset_index(name='avg_traction_force')
)

Выход:

  car_brand speed_observation  avg_traction_force
0      audi           (0, 25]            3.500000
1      audi          (25, 50]            3.333333
2      ford           (0, 25]            3.516667
3      ford          (25, 50]           12.500000
4      seat           (0, 25]            6.000000
5      seat          (25, 50]           13.000000
...