Я работаю над geolife
набором данных , который содержит GPS-трек с отметкой времени пользователей в текстовом файле (.plt
). Каждый текстовый файл содержит точки GPS пользователя за одну поездку. Поэтому я импортировал набор данных в postgres
с помощью сценария python.
Поскольку файлы названы строкой чисел в соответствии с временем начала поездки (так, например, файл, содержащий поездку в таблице ниже, 20070920074804.plt
), даю trip id (session_id
) имя файла (без расширения). Это необработанный GPS в этой таблице trajectories
.
user_id | session_id | timestamp | lat | lon | alt
---------+-------------------+------------------------+-----------+------------+-----
11 | 20070920074804 | 2007-09-20 07:48:04+01 | 28.19737 | 113.006795 | 71
11 | 20070920074804 | 2007-09-20 08:07:09+01 | 28.197685 | 113.006792 | 87
11 | 20070920074804 | 2007-09-20 08:07:10+01 | 28.197685 | 113.00679 | 87
11 | 20070920074804 | 2007-09-20 14:03:50+01 | 28.197342 | 113.007422 | 62
11 | 20070920074804 | 2007-09-20 14:04:59+01 | 28.197108 | 113.00734 | 62
11 | 20070920074804 | 2007-09-20 14:05:01+01 | 28.197088 | 113.00727 | 62
Для анализа я создал другую таблицу trips_metrics
, в которой вычисляю метрики поездки из таблицы trajectories
и вставляю результат в trip_metrics
. Среди вычисляемых значений - расстояние поездки (haversine
) и продолжительность (start time - end time
).
Затем я заметил кое-что странное: пользователь взял 8hrs
поездки, но преодолел расстояние 321m
. Тщательно просматривая файл поездки, я заметил скачок времени поездки, предполагающий перерыв в поездке (возможно, пользователь остается на несколько часов, а затем продолжает). Пример находится в row 3
и row 4
в таблице выше.
Чтобы получить точное время поездки, мне нужно разделить поездки с этими случаями таким образом, чтобы, если временной интервал между последовательными строками превышает 30 минут, это следует рассматривать как новую поездку (т.е. новый идентификатор).
Я намерен добавить di git ..02, ..03, ..
к текущему session_id
поездки в моей таблице trajectories
перед фактическим вычислением показателей поездок (т. е. изменение таблицы trajectories
). Итак, для примера в таблице выше я хочу разбить его следующим образом:
user_id | session_id | timestamp | lat | lon | alt
---------+-------------------+------------------------+-----------+------------+-----
11 | 20070920074804 | 2007-09-20 07:48:04+01 | 28.19737 | 113.006795 | 71
11 | 20070920074804 | 2007-09-20 08:07:09+01 | 28.197685 | 113.006792 | 87
11 | 20070920074804 | 2007-09-20 08:07:10+01 | 28.197685 | 113.00679 | 87
11 | 2007092007480402 | 2007-09-20 14:03:50+01 | 28.197342 | 113.007422 | 62
11 | 2007092007480402 | 2007-09-20 14:04:59+01 | 28.197108 | 113.00734 | 62
11 | 2007092007480402 | 2007-09-20 14:05:01+01 | 28.197088 | 113.00727 | 62
Обратите внимание, как я назначаю session_id
для новой поездки (поскольку время между ними составляет более 30 минут).
Как я могу сделать это изменение или изменение в моей исходной таблице GPS (trajectories
) в postgres
?
EDIT
A: Первый запрос в ответе от @GMB работает, однако он дает каждой новой строке session_id
в столбце new_session_id
.
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
| user_id | session_id | timestamp | lat | lon | alt | is_gap | new_session_id |
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
| 11 | 20070920074804 | 2007-09-20 07:48:04+01 | 28.19737 | 113.006795 | 71 | | 20070920074804 |
| 11 | 20070920074804 | 2007-09-20 08:07:09+01 | 28.197685 | 113.006792 | 87 | 1 | 2007092007480401 |
| 11 | 20070920074804 | 2007-09-20 08:07:10+01 | 28.197685 | 113.00679 | 87 | 1 | 2007092007480402 |
| 11 | 20070920074804 | 2007-09-20 14:03:50+01 | 28.197342 | 113.007422 | 62 | 1 | 2007092007480403 |
| 11 | 20070920074804 | 2007-09-20 14:04:59+01 | 28.197108 | 113.00734 | 62 | 1 | 2007092007480404 |
| 11 | 20070920074804 | 2007-09-20 14:05:01+01 | 28.197088 | 113.00727 | 62 | 1 | 2007092007480405 |
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
Ожидаемый результат:
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
| user_id | session_id | timestamp | lat | lon | alt | is_gap | new_session_id |
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
| 11 | 20070920074804 | 2007-09-20 07:48:04+01 | 28.19737 | 113.006795 | 71 | | 20070920074804 |
| 11 | 20070920074804 | 2007-09-20 08:07:09+01 | 28.197685 | 113.006792 | 87 | | 20070920074804 |
| 11 | 20070920074804 | 2007-09-20 08:07:10+01 | 28.197685 | 113.00679 | 87 | 1 | 2007092007480401 |
| 11 | 20070920074804 | 2007-09-20 14:03:50+01 | 28.197342 | 113.007422 | 62 | 1 | 2007092007480401 |
| 11 | 20070920074804 | 2007-09-20 14:04:59+01 | 28.197108 | 113.00734 | 62 | 1 | 2007092007480401 |
| 11 | 20070920074804 | 2007-09-20 14:05:01+01 | 28.197088 | 113.00727 | 62 | 1 | 2007092007480401 |
+---------+----------------+------------------------+-----------+------------+-----+--------+------------------+
Идея состоит в том, чтобы присвоить «появляющейся» поездке новый идентификатор old_session_id + 01
. При обнаружении еще одной возникающей поездки ему следует присвоить old_session_id + 02
и т. Д.
B: Второй запрос с опцией обновления содержит синтаксическую ошибку:
update trajectories t
from (
select
t.*,
case when sum(is_gap) over(partition by session_id order by timestamp) > 0
then session_id * 100 + sum(is_gap) over(partition by session_id order by timestamp)
else session_id
end new_session_id
from (
select
t.*,
(timestamp > lag(timestamp) over(partition by session_id order by timestamp))::int is_gap
from trajectories t
) t
) t1
set session_id = t1.new_session_id
where t1.session_id = t.session_id and t1.timestamp = t.timestamp
ERROR: syntax error at or near "from"
LINE 2: from (