【问题标题】:Correcting Clock Drift in Time Series校正时间序列中的时钟漂移
【发布时间】:2020-06-05 19:02:41
【问题描述】:

首先,我为这个请求的命名道歉——我有点不确定这个技术到底是什么标签。我会尽量解释清楚。

我在现场有记录器来收集环境数据。他们的内部时钟在被放置在现场之前会与“实时”同步。然而,内部时钟在其整个使用寿命期间开始偏离实时。例如,在现场工作一年后,数据文件仍会报告整点的日志记录(例如 20:00:00),但实际时间可能是 20:07。记录器通常运行多年,日志速率可以在 1 分钟到 4 小时之间(尽管一个文件中的日志速率始终相同)。 我以前一直在使用在内部完成此同步的软件。我现在正在使用不幸的是不包含此类功能的软件;然而,它确实有一个 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}}

我们将不胜感激任何帮助,甚至是关于研究方向的建议。

谢谢。

【问题讨论】:

  • 这有两个步骤。第一个是根据边界条件校正观察时间。您似乎已经解决了上述问题(手动?)。第二个是重采样,仅当您要求所有传感器之间的观察时间相等时才需要。你有这个要求吗?如果不是,我不会为重新采样而烦恼,因为它会引入一种猜测(因为没有更好的词)并且取决于过滤器的选择等。
  • 传感器不需要相等;它们在不同时间在现场下载。然而,“成为”列表只是手动完成的;我实际上不确定如何使用 python 来实现这一点。感谢您的回答。
  • 我明白了。我在下面提供了一个我之前写的函数来完成这部分。

标签: python pandas time time-series


【解决方案1】:

Sebs 的回答确实有助于理解这个概念,但我无法让它在没有错误的情况下正常工作。

我最终使用了一些不同的东西(但使用了来自 Sebs 答案的想法)。安装记录器时会同步时间,所以我可以锚定它。

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)

【讨论】:

    【解决方案2】:

    我会做这样的事情(startend 的类型转换可能需要一些改进,因为它有点笨拙,但它确实有效):

    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
    

    它计算开始和结束之间的时间跨度(以纳秒为单位),并将任一端点替换为已知时间,以创建一个新的规则间隔时间序列。请注意,这取决于您陈述的假设“一个文件中的日志速率始终相同”。不规则采样的数据集需要不同的方法。

    您可以使用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
    

    【讨论】:

    • 谢谢!我已经完全复制了您的示例,但是我收到错误“ValueError:值的长度与索引的长度不匹配”。
    • 抱歉,不知何故,pd.RangeIndex 创建了一个长度为 10 的索引,而具有相同参数的 Python range 的长度为 11。它现在应该可以工作了。
    • 我有一个类似的问题,但是我没有“真实”的开始和结束时间(事实上,“记录器”开始/结束数据收集的时间略有不同),采样是不规则(由环境噪声决定)。如何解决这样的问题?
    猜你喜欢
    • 2022-07-09
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2016-10-13
    相关资源
    最近更新 更多