Исправление смещения часов во временных рядах - PullRequest
1 голос
/ 21 февраля 2020

Во-первых, я прошу прощения за наименование этого запроса - я немного не уверен, что именно обозначено в технике. Я постараюсь объяснить как можно лучше.

У меня есть регистраторы на местах, собирающие данные об окружающей среде. Их внутренние часы синхронизируются с «реальным временем» до того, как были помещены в поле. Однако внутренние часы начинают отдаляться от реального времени в течение всего срока эксплуатации. Например, после года, проведенного в поле, файл данных все еще сообщает о регистрации в час (скажем, 20:00:00), но реальное время может быть 20:07. Регистраторы часто работают несколько лет, и скорость записи может варьироваться от 1 минуты до 4 часов (хотя всегда одна и та же скорость записи в одном файле). Ранее я использовал программное обеспечение, которое выполнило эту синхронизацию c внутри. Сейчас я использую программное обеспечение, которое, к сожалению, не содержит такой функции; однако у него есть API, который позволяет использовать python для «предварительной обработки» работы перед добавлением к существующему набору данных.

Цель состоит в том, чтобы «растянуть» или «отстать» или, в более общем смысле, выровняйте время так, чтобы последний журнал равнялся «истинному времени». Простой пример:

Оригинал:

Datetime,Value
24/03/2018 10:00:00,25.966
24/03/2018 11:00:00,27.402
24/03/2018 12:00:00,29.137
24/03/2018 13:00:00,32.001
24/03/2018 14:00:00,33.661
24/03/2018 15:00:00,34.852
24/03/2018 16:00:00,34.252
24/03/2018 17:00:00,31.605
24/03/2018 18:00:00,30.033
24/03/2018 19:00:00,27.790
24/03/2018 20:00:00,26.214

Стать:

Datetime,Value
24/03/2018 10:00:00,25.966
24/03/2018 11:00:42,27.402
24/03/2018 12:01:24,29.137
24/03/2018 13:02:06,32.001
24/03/2018 14:02:48,33.661
24/03/2018 15:03:30,34.852
24/03/2018 16:04:12,34.252
24/03/2018 17:04:54,31.605
24/03/2018 18:05:36,30.033
24/03/2018 19:06:18,27.790
24/03/2018 20:07:00,26.214

Какие существуют методы для синхронизации / выравнивания данных? Требуется ли повторная выборка? Или есть гораздо более простой способ для достижения этой цели?

Дата и время

df = {'2018-03-24 10:00:00': {'Value': 25.966}, '2018-03-24 11:00:00': {'Value': 27.402},'2018-03-24 12:00:00': {'Value': 29.137}, '2018-03-24 13:00:00': {'Value': 32.001},'2018-03-24 14:00:00': {'Value': 33.661}, '2018-03-24 15:00:00': {'Value': 34.852},'2018-03-24 16:00:00': {'Value': 34.252}, '2018-03-24 17:00:00': {'Value': 31.605},'2018-03-24 18:00:00': {'Value': 30.033}, '2018-03-24 19:00:00': {'Value': 27.790},'2018-03-24 20:00:00': {'Value': 26.214}}

Любая помощь или даже предложения о том, в каком направлении следует искать, будут высоко оценены.

Thankyou.

Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Ответ Себса действительно помог с концепцией, но я просто не смог заставить ее работать без ошибок.

В итоге я использовал что-то немного другое (но использовал идеи из ответа Себса). Время синхронизируется при установке логгера, поэтому я смог закрепить это.

df = pd.read_csv(file, skiprows=sRow, index_col=0, parse_dates=True, dayfirst=True, usecols=[cols for cols in range(5)])

def TimeAlign(df):
    logStart = df.index[0]
    logEnd = df.index[-1]
    logNum = len(df)
    logFreq = pd.Timedelta(df.index[1] - df.index[0])
    logDiff = pd.Timedelta(pd.to_datetime(input("Enter real time of last log (e.g 01/01/2020 10:07):")) - logEnd)
    logDrift = pd.Timedelta(logDiff / (logNum -1) + logFreq)

    df.index = pd.date_range(start=logStart, periods=logNum, freq=logDrift)
    df.index = df.index.round('1s')

    df.to_csv('TimeAlign.csv', float_format='%.3f' )

    return df

TimeAlign(df)
1 голос
/ 21 февраля 2020

Я хотел бы сделать что-то вроде этого (приведение типов start и end может использовать некоторые улучшения, поскольку это немного неуклюже, но это работает):

def dedrift(df, start=None, end=None):
    epochs = pd.to_datetime(df.index).astype(int) 
    first = pd.to_datetime(start).to_datetime64().astype(int) if start is not None else epochs[0] 
    last = pd.to_datetime(end).to_datetime64().astype(int) if end is not None else epochs[-1] 
    interval = (last - first)//(len(df) - 1) 
    df['dedrifted'] = pd.to_datetime(range(first, last+1, interval)) 
    return df

Он рассчитывает временной интервал ( в наносекундах) между началом и окончанием sh и заменяет любую конечную точку на известное время для создания нового регулярно разнесенного временного ряда. Обратите внимание, что это зависит от вашего предположения «всегда одна и та же скорость записи в одном файле». Набор данных с нерегулярной выборкой потребует другого подхода.

Вы можете использовать start и / или end, чтобы обеспечить известные граничные условия (например, точное время установки или удаления датчика):

>>> df = pd.DataFrame({'2018-03-24 10:00:00': {'Value': 25.966}, '2018-03-24 11:00:00': {'Value': 27.402},'2018-03-24 12:00:00': {'Value': 29.137}, '2018-03-24 13:00:00': {'Value': 32.001},'2018-03-24 14:00:00': {'Value': 33.661}, '2018-03-24 15:00:00': {'Value': 34.852},'2018-03-24 16:00:00': {'Value': 34.252}, '2018-03-24 17:00:00': {'Value': 31.605},'2018-03-24 18:00:00': {'Value': 30.033}, '2018-03-24 19:00:00': {'Value': 27.790},'2018-03-24 20:00:00': {'Value': 26.214}}).T
>>> dedrift(df, end='2018-03-24 20:07:00')
                      Value           dedrifted
2018-03-24 10:00:00  25.966 2018-03-24 10:00:00
2018-03-24 11:00:00  27.402 2018-03-24 11:00:42
2018-03-24 12:00:00  29.137 2018-03-24 12:01:24
2018-03-24 13:00:00  32.001 2018-03-24 13:02:06
2018-03-24 14:00:00  33.661 2018-03-24 14:02:48
2018-03-24 15:00:00  34.852 2018-03-24 15:03:30
2018-03-24 16:00:00  34.252 2018-03-24 16:04:12
2018-03-24 17:00:00  31.605 2018-03-24 17:04:54
2018-03-24 18:00:00  30.033 2018-03-24 18:05:36
2018-03-24 19:00:00  27.790 2018-03-24 19:06:18
2018-03-24 20:00:00  26.214 2018-03-24 20:07:00
...