如何在Ruby中规范化和插值timeseries中缺失的值?

如何在Ruby中规范化和插值timeseries中缺失的值?,ruby,arrays,time-series,Ruby,Arrays,Time Series,假设我有一个Ruby数组,其中包含时间/值对数组,如: [ # about 9:00 AM on consecutive days [<DateTime: 2014-05-15T09:00:00Z>, 56], [<DateTime: 2014-05-16T09:06:00Z>, 57], # ... missing data for May 17th, 2014 # ... missing data for May 18th, 2014

假设我有一个Ruby数组,其中包含时间/值对数组,如:

[
  # about 9:00 AM on consecutive days
  [<DateTime: 2014-05-15T09:00:00Z>, 56],
  [<DateTime: 2014-05-16T09:06:00Z>, 57],
    # ... missing data for May 17th, 2014
    # ... missing data for May 18th, 2014
  [<DateTime: 2014-05-19T08:57:00Z>, 61],
  # ...
]
[
#连续几天上午9点左右
[, 56],
[, 57],
#…2014年5月17日数据缺失
#…2014年5月18日数据缺失
[, 61],
# ...
]
请注意,(1)并非每天在同一时间收集这些值,(2)缺少一些值

我想通过以下方式规范化数据:

  • 重新采样,使它们在时间和空间上均匀分布
  • 插入任何缺少的值
  • 以编程方式这样做的正确方法是什么

    更新1
    您希望如何插值?在您的示例中,[58,59]、[58,60]和[59,60]也同样合理

    预期值将取决于所使用的插值策略(例如,线性、二次等),因此我无法提供准确答案


    我愿意接受任何以最小误差(例如<0.1%)预测原始实际数据点的插值策略。我愿意接受任何导致时间序列观测值间隔相等的规范化策略

    a
    是当前数组的第一个元素,
    b
    是当前数组的最后一个元素。这个解决方案是98%,最后一件事是从最后一个日期开始增加/减少几分钟,使之成为上午9点(因此纠正
    天.轮之间的差异)

    days=b.first-a.first
    每天=(b.last-a.last)/天
    天.轮.时间.地图.带指数(1).注射([a])do | arr,(|,i)|
    arr[[#,56],
    [#, 57.250651380927565], 
    [#, 58.501302761855136], 
    [#, 59.7519541427827], 
    [#, 61.002605523710265]]
    
    可以使用样条插值。下面是一个使用的示例:

    输出:

    2014-05-15T09:00:00+00:00: 56.0                 # exact value
    2014-05-16T09:00:00+00:00: 56.995496729398646   # interpolated value
    2014-05-17T09:00:00+00:00: 58.18937752978536    # interpolated value
    2014-05-18T09:00:00+00:00: 59.55365781173006    # interpolated value
    2014-05-19T09:00:00+00:00: 61.0030489943531     # extrapolated value
    

    你能发布预期的输出吗?你想如何插值?在你的例子中,[58,59]、[58,60]和[59,60]同样是合理的。从日期范围来看,周末似乎没有收集数据。因此,将工作日作为您的时间框架可能会解决您的(1-时间要求等间隔){@Stefan,@MichaelKohl}:我已经更新了问题正文,以反映我对您问题的回答@乌代:不幸的是,这只是巧合(我编造了这些数据)。真正的数据是几年的数据,几乎每天都有测量(但有时每天发生一次以上,有时几周都没有数据)。我要做的第一件事是绘制它,看看是否有任何明显的模式/异常(例如异常值),以及是否需要最小二乘拟合。您是否可以发布数据链接(例如,在GitHub上)?
    require 'date'
    require 'spliner'
    
    arr = [
      [DateTime.new(2014,5,15,9), 56],
      [DateTime.new(2014,5,16,9,6), 57],
      [DateTime.new(2014,5,19,8,57), 61]
    ]
    
    spline = Spliner::Spliner.new(arr.to_h, extrapolate: '10%')
    
    (DateTime.new(2014,5,15,9)..DateTime.new(2014,5,19,9)).each do |date|
      puts "#{date}: #{spline[date]}"
    end
    
    2014-05-15T09:00:00+00:00: 56.0                 # exact value
    2014-05-16T09:00:00+00:00: 56.995496729398646   # interpolated value
    2014-05-17T09:00:00+00:00: 58.18937752978536    # interpolated value
    2014-05-18T09:00:00+00:00: 59.55365781173006    # interpolated value
    2014-05-19T09:00:00+00:00: 61.0030489943531     # extrapolated value