#python #pandas #for-loop #if-statement #sum
Вопрос:
У меня есть следующие фиктивные данные:
data = {"trip_id": ["a", "a", "a", "a", "b", "b", "b", "c", "c", "c", "c", "c"],
"distance": [5, 10, 2, 12, 20, 1, 15, 2, 3, 5, 0, 28],
"value": [32, 46, 132, 45, 68, 123, 56, 54, 32, 89, 10, 39],
"timestamp": ["2021-05-09 10:12:18", "2021-06-19 08:22:18", "2021-01-09 15:20:00", "2021-01-09 18:30:18",
"2021-04-09 24:11:18", "2021-02-19 08:12:18", "2021-06-11 08:56:18", "2021-06-11 08:54:18",
"2021-06-09 18:12:18", "2021-06-19 16:10:18", "2021-06-03 18:12:18", "2021-06-12 08:22:18"]
}
df = pd.DataFrame(data, columns = ["trip_id", "distance", "value", "timestamp"])
df
>>
trip_id distance value timestamp
0 a 5 32 2021-05-09 10:12:18
1 a 10 46 2021-06-19 08:22:18
2 a 2 132 2021-01-09 15:20:00
3 a 12 45 2021-01-09 18:30:18
4 b 20 68 2021-04-09 24:11:18
5 b 1 123 2021-02-19 08:12:18
6 b 15 56 2021-06-11 08:56:18
7 c 2 54 2021-06-11 08:54:18
8 c 3 32 2021-06-09 18:12:18
9 c 5 89 2021-06-19 16:10:18
10 c 0 10 2021-06-03 18:12:18
11 c 28 39 2021-06-12 08:22:18
Я хотел бы сжать значения на trip_id каждые 30 метров столбца расстояния. Для этого я пытаюсь:
current_trip_id = ""
dist_segment = []
for index,row in df.iterrows():
if row["trip_id"] == current_trip_id:
if sum(dist_segment) <= 30:
# compute trip characteristics every 30m
sorted_trip_char = df.sort_values(["trip_id", "timestamp"])
grouped_trip_char = sorted_trip_char.groupby("trip_id")
agg_trip_char = grouped_trip_char.agg({'trip_id': 'first',
'distance':'sum',
'value': 'mean',
'timestamp':['first', 'last']
})
else:
# store trip characteristics to another line up to 30m
print("More than 30m in index", index)
# Update loop
current_trip_id = row["trip_id"]
dist_segment.append(row["distance"])
Однако я не вижу, как я все еще могу сохранить идентификатор и перейти к новой агрегации значений.
Это тот результат, который мне нужен:
agg_trip_char
>>
trip_id distance value timestamp
first sum mean first last
trip_id
a a 29 63.75 2021-01-09 15:20:00 2021-06-19 08:22:18
b b 21 95.50 2021-02-19 08:12:18 2021-06-11 08:56:18
b b 15 56 2021-06-11 08:56:18 2021-06-11 08:56:18
c c 10 46.25 2021-06-11 08:54:18 2021-06-03 18:12:18
c c 28 39 2021-06-12 08:22:18 2021-06-12 08:22:18
Комментарии:
1.Пожалуйста, проверьте правильные значения
timestamp
first
иlast
в вашем ожидаемом выходе. Поскольку группы были разделены на 30-метровые расстояния, значения должны быть разными, верно ? Например,last
во 2-й строке должно быть2021-04-09 24:11:18
правильно ? Так как это последняя из первой 30-метровой группыtrip_id
b
.
Ответ №1:
Вы можете изменить свои коды следующим образом:
- сортировка столбцов
df_out = df.sort_values(["trip_id", "timestamp"])
- Создавайте группы на расстоянии каждые 30 м в пределах одного и того же
trip_id
g = df_out.groupby('trip_id')['distance'].cumsum() // 30
Здесь мы получаем суммарную сумму distance
в пределах конкретного trip_id
, используя .groupby()
.cumsum()
. Затем используйте целочисленное деление на 30, чтобы разделить каждые 30 м на разные групповые номера.
- Агрегируйте столбцы
df_out2 = (df_out.groupby(['trip_id', g])
.agg({'trip_id': 'first',
'distance':'sum',
'value': 'mean',
'timestamp':['first', 'last']
}).droplevel(-1)
)
Результат:
print(df_out2)
trip_id distance value timestamp
first sum mean first last
trip_id
a a 29 63.75 2021-01-09 15:20:00 2021-06-19 08:22:18
b b 21 95.50 2021-02-19 08:12:18 2021-04-09 24:11:18
b b 15 56.00 2021-06-11 08:56:18 2021-06-11 08:56:18
c c 5 32.00 2021-06-03 18:12:18 2021-06-11 08:54:18
c c 33 64.00 2021-06-12 08:22:18 2021-06-19 16:10:18
Если мы не отсортируем столбцы, результат будет более похож на ожидаемый результат:
#df_out = df.sort_values(["trip_id", "timestamp"])
df_out = df
g = df_out.groupby('trip_id')['distance'].cumsum() // 30
df_out2 = (df_out.groupby(['trip_id', g])
.agg({'trip_id': 'first',
'distance':'sum',
'value': 'mean',
'timestamp':['first', 'last']
}).droplevel(-1)
)
Результат:
print(df_out2)
trip_id distance value timestamp
first sum mean first last
trip_id
a a 29 63.75 2021-05-09 10:12:18 2021-01-09 18:30:18
b b 21 95.50 2021-04-09 24:11:18 2021-02-19 08:12:18
b b 15 56.00 2021-06-11 08:56:18 2021-06-11 08:56:18
c c 10 46.25 2021-06-11 08:54:18 2021-06-03 18:12:18
c c 28 39.00 2021-06-12 08:22:18 2021-06-12 08:22:18
Тем не менее, кажется разумным отсортировать trip_id
и timestamp
, если вам нужно, следовать временной последовательности. Поэтому, пожалуйста, ознакомьтесь с вашей реальной ситуацией и выберите один из вариантов соответственно.