Pandas группирует данные до первого появления шаблона

#python #pandas

#python #pandas

Вопрос:

У меня есть фрейм данных, который содержит аварии автомобилей, они могут быть «L» для легких или «S» для сильных:

 |car_id|type_acc|datetime_acc|
------------------------------
|   1  |    L   | 2020-01-01 | 
|   1  |    L   | 2020-01-05 |
|   1  |    S   | 2020-01-07 |
|   1  |    L   | 2020-01-09 |
|   2  |    L   | 2020-01-04 |
|   2  |    L   | 2020-01-10 |
|   2  |    L   | 2020-01-12 |
 

Я хотел бы получить столбец, который считается до первого ‘S’ и делит количество вхождений между максимальным и минимальным ‘L’, поэтому результат будет:

 |car_id|freq_acc|
-----------------
|   1  |    2   | # 4 days (from 1 to 5) / 2 number of 'L' before first 'S'
|   2  |    8   | # 8 days(from 4 to 12) and no 'S'
 

Возможно ли такое? Спасибо

Ответ №1:

Вы можете использовать np.ptp для вычисления максимальной и минимальной разницы:

 # find first by S by car_id
df['eq_s'] = df.groupby('car_id')['type_acc'].transform(lambda x: x.eq('S').cumsum())

# compute stats based on previous computation, keeping only the first group
groups = df[df['eq_s'].eq(0)].groupby(['car_id']).agg({'datetime_acc': np.ptp}).reset_index()

# rename
res = groups.rename(columns={'datetime_acc': 'freq_acc'})
print(res)
 

Вывод

    car_id freq_acc
0       1   4 days
1       2   8 days
 

Прежде чем что-либо делать, убедитесь, что datetime_acc является столбцом datetime, выполнив:

 df['datetime_acc'] = pd.to_datetime(df['datetime_acc'])
 

Первый шаг:

 # find first by S by car_id
df['eq_s'] = df.groupby('car_id')['type_acc'].transform(lambda x: x.eq('S').cumsum())
 

создаст новый столбец, в котором единственными представляющими интерес значениями являются 0, то есть те, которые находятся перед первым S. На втором шаге мы сохраняем только эти значения и выполняем стандартный groupby:

 # compute stats based on previous computation, keeping only the first group
groups = df[df['eq_s'].eq(0)].groupby(['car_id']).agg({'datetime_acc': np.ptp}).reset_index()