Ищете метод организации данных GPS от дней до сессий (случаи непрерывной передачи данных на следующий день) - PullRequest
0 голосов
/ 10 июля 2019

У меня есть тысячи записанных точек GPS, сохраненных по дате и времени, разбитых на исходные видеоролики, каждая из которых создавалась каждую минуту.

Сеансы - это когда GPS-рекордер запускается и до его окончания, чтов некоторых случаях пошел с 9 вечера до 4 утра следующего дня.Они разбиты во времени по крайней мере на 6 часов, но обычно больше на 12 часов.

К сожалению, когда я собирал необработанные данные, не было никакого способа узнать, разделяю ли я один сеанс на следующий и по крайней мередюжину раз блок записи, который начинался с одной даты и простирался до следующей, был разбит на части.Теперь я пытаюсь выяснить, как их реорганизовать обратно.

Все данные хранятся в базе данных sqlite со схемой, подобной следующей:

session
    date
    videos # relationship(Video)

Video:
    datetime # includes the minute of the day it was recorded
    coordinates # relationship(Coordinates)

Coordinate:
    latitude = string # (not float to avoid loss of precision)
    longitude = string 
    datetime = # includes the date, minute, and second

Я попробовал такой метод перебораэто

def find_gaps():
   """
       Assume the bulk of a session's videos are in the correct
       location but the head or tail may not be

       12567
       12,567
       89012567
       89012, 567

   """

   for session in db.Session.query.order_by(db.Session.date.asc()):
       videos = list(session.videos)
       blocks = list()
       block = [videos.pop(0)]
       for video in videos:
           delta = video.datetime - block[-1].datetime
           minutes = delta.seconds / 60
           print(delta.days, minutes)
           if minutes > 15:
               print(video.name, minutes)
               blocks.append(block)
               block = [video]
           else:
               block.append(video)

       if block:
           blocks.append(block)

   if len(blocks) > 1:
       print(len(blocks))

, но я никогда не реализовывал логику сортировки, так как я понял, что все равно будут сохраняться сеансы, которые перекрывают две даты.

Другая идея, которую я имел, состояла в том, чтобы просмотреть все видеозаписи (datetime- часы и минуты) в наборах перекрывающихся трех дней (предыдущий день, текущий день, следующий день), но я не мог придумать, как найти реальные сессии.

Не имеет значения

IЯ записал как мои поездки за Lyft, так и мои поездки из Денвера в Анкоридж, Аляску и обратно (я люблю водить).Данные о поездке для меня важнее, но они также самые сложные, особенно данные за последние годы.Я разбил свою солнечную крышу из заблудшей скалы, а затем порезал шину, так что в итоге я потерял ~ 3200 миль в свободное время и приклеил крышу воздуховода за 12 часов с 6-часовой остановкой на скорости 70 км / ч (~ 45 миль в час).

1 Ответ

0 голосов
/ 10 июля 2019

Если у вас последняя версия SQLite, она будет поддерживать оконные функции . Если у вас нет последней версии, вы можете обновить ее довольно легко. Я настоятельно рекомендую использовать это.

Оконные функции предоставляют в SQL способ эффективно упорядочивать набор данных, а затем сравнивать соседей, запускать вкладки и т. Д. Синтаксис немного громоздкий, и их решение обычно приводит к вложенным запросам. Требуется немного привыкнуть.

Для начала напишем запрос, который даст нам Video с указанием даты и времени предыдущего видео (предупреждение, все запросы не проверены и могут быть повреждены)

SELECT datetime
  , coordinates
  , lag(datetime) OVER (ORDER BY strftime('%s',datetime)) as last_datetime
FROM Video

(Обратите внимание, что кадр по умолчанию неограничен перед текущей строкой, что означает, что у нас есть доступ к предыдущим видео, но не к будущим. Я буду использовать этот факт снова, но не буду это замечать.)

Теперь давайте сделаем такой же запрос, за исключением того, что мы знаем, какие записи начинают сеанс, и я определю его, поскольку в течение предыдущего часа не было ни одной записи.

SELECT datetime
  , coordinates
  , CASE
       WHEN strftime('%s',datetime) - strftime('%s',last_datetime) < 3600
       THEN 0
       ELSE 1
    END as is_session_start
FROM (
    SELECT datetime
      , coordinates
      , lag(datetime) OVER (ORDER BY strftime('%s',datetime)) as last_datetime
    FROM Video
  ) AS video_and_prev_datetime

А теперь мы помечаем каждое видео датой и временем начала его сеанса.

SELECT datetime
  , coordinates
  , MAX (
      CASE
        WHEN is_session_start = 1
        THEN strftime('%s',datetime)
        ELSE 0
      END
    ) OVER (
      ORDER BY strftime('%s',datetime)
    ) AS session_start
FROM (
    SELECT datetime
      , coordinates
      , CASE
           WHEN strftime('%s',datetime) - strftime('%s',last_datetime) < 3600
           THEN 0
           ELSE 1
        END as is_session_start
    FROM (
        SELECT datetime
          , coordinates
          , lag(datetime) OVER (ORDER BY strftime('%s',datetime)) as last_datetime
        FROM Video
      ) AS video_and_prev_datetime
  ) as video_and_session_start

А теперь у вас есть видео, классифицированные по времени начала сеанса.


Если вы предпочитаете делать это в коде, я рекомендую просто отсортировать Video по strftime('%s',datetime) и затем выполнить то же самое «сравнить с последними, отследить начало сеансов и добавить их» в коде. Но с учетом того, что оконные функции с течением времени поступают во все большее и большее количество баз данных, вы также можете узнать, как их использовать, как я только что продемонстрировал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...