将时间序列值的Ruby数组映射到加权间隔

约翰·费米内拉

我有一个由Ruby组成的数组数组,该数组表示对随时间记录的指标的一系列观察。每个内部数组都有两个元素:

  • TimeUTC中的一个实例,它描述观察记录的时间
  • 观察值的整数

例如,我们可能会有类似的内容:

[
  [<Time: 2014-01-15 @ 18:00>, 100],
  [<Time: 2014-01-16 @ 06:00>, 200],
  [<Time: 2014-01-16 @ 12:00>, 300],
  [<Time: 2014-01-16 @ 23:00>, 400],
  [<Time: 2014-01-17 @ 12:00>, 500],
  [<Time: 2014-01-18 @ 03:00>, 600],
  [<Time: 2014-01-18 @ 06:00>, 700],
]

当前的问题是将其转换为每个日期的加权值数组:

[
  [<Date: 2014-01-15>, 100],
  [<Date: 2014-01-16>, 229],
  ...
]

通过以下过程获得上述数组中每天的值:

  1. 将一天分成一系列间隔,间隔由每个观察值和一天的边界界定。

    例如,由于1月16日的观测时间为06:00、12:00和23:00,因此将其细分为00:00-06:00、06:00-12:00、12:00-23 :00和23:00-00:00。

  2. 每个时间间隔的值等于时间间隔开始时的观察值,如果等于一天的开始,则等于上一次进行的观察。

    例如,由于在06:00记录的值为200,所以1月16日的06:00-12:00间隔的值为200。

    1月15日的00:00-06:00间隔的值100,因为值100是在开始一天的那一点记录的最后一个观测值。

  3. 每个时间间隔的加权值等于其值乘以该时间间隔中所有时间间隔的长度的分数。

    例如,1月16日06:00-12:00间隔的加权值为50(200 * 0.25)。

  4. 每天的最终加权值是其间隔的加权值的总和,强制为整数。

    例如,1月16日的加权值为229,因为:

    (100*(6/24) + 200*(6/24) + 300*(11/24) + 400*(1/24)).to_i = 229

数组中的第一点是一种特殊情况:一天从那里开始,而不是从00:00开始,因此1月15日只有一个时间间隔:18:00-00:00,值为100,因此加权值也为100

关于如何开始解决这个问题的任何建议?

卡里·斯沃夫兰

我假设没有日子没有条目。

我发现先转换Time对象数组很方便我用于转换的规则如下(arb指的是一个任意值,也可能相等val):

  • 在第一天,将单个元素[dt, val]替换为三个元素:
    • [dt1, val]dt1同一时间在哪里00:00:00
    • [dt2, arb]dt2同一时间在哪里23:59:59
    • [dt3, val]dt3一天后一天在哪里00:00:00
  • 对于最后一天,如果[dt, val]当天的最后一个元素,请添加一个元素[dt1, arb],其中dttime是相同的日期23:59:59
  • 对于第一天和最后一天以外的每一天,如果[dt, val]是当天的最后一个元素,则添加两个元素:
    • [dt1, arb]dt1同一时间在哪里23:59:59
    • [dt2, val]dt2一天后一天在哪里00:00:00

假设以下是您的初始数组。为了清楚起见,我用字符串(让我来代替"23:59:59""24:00"):

arr = [
  ["2014-01-15 18:00", 100],

  ["2014-01-16 06:00", 200],
  ["2014-01-16 12:00", 300],
  ["2014-01-16 23:00", 400],

  ["2014-01-17 12:00", 500],

  ["2014-01-18 03:00", 600],
  ["2014-01-18 06:00", 700]
]

应用上述规则后,我们获得:

arr1 = [
  ["2014-01-15 00:00", 100],
  ["2014-01-15 24:00", 100],
  ["2014-01-16 00:00", 100],

  ["2014-01-16 06:00", 200],
  ["2014-01-16 12:00", 300],
  ["2014-01-16 23:00", 400],
  ["2014-01-16 24:00", 400],
  ["2014-01-17 00:00", 400],

  ["2014-01-17 12:00", 500],
  ["2014-01-17 24:00", 500],
  ["2014-01-18 00:00", 500],

  ["2014-01-18 03:00", 600],
  ["2014-01-18 06:00", 700],
  ["2014-01-18 24:00", 700]
]

或按日期分组的元素,

arr1 = [
  ["2014-01-15 00:00", 100],
  ["2014-01-15 24:00", 100],

  ["2014-01-16 00:00", 100],
  ["2014-01-16 06:00", 200],
  ["2014-01-16 12:00", 300],
  ["2014-01-16 23:00", 400],
  ["2014-01-16 24:00", 400],

  ["2014-01-17 00:00", 400],
  ["2014-01-17 12:00", 500],
  ["2014-01-17 24:00", 500],

  ["2014-01-18 00:00", 500],
  ["2014-01-18 03:00", 600],
  ["2014-01-18 06:00", 700],
  ["2014-01-18 24:00", 700]
]

实现这些规则的代码应该很简单。一旦有了arr1,用Enumerable#chunk创建一个枚举数

enum = arr1.chunk { |a| a.first[0,10] } 
  #=> #<Enumerator: #<Enumerator::Generator:0x000001010e30d8>:each>

让我们看看的元素enum

enum.to_a
  #=> [["2014-01-15", [["2014-01-15 00:00", 100], ["2014-01-15 24:00", 100]]],
  #    ["2014-01-16", [["2014-01-16 00:00", 100], ["2014-01-16 06:00", 200],
  #      ["2014-01-16 12:00", 300], ["2014-01-16 23:00", 400],
  #      ["2014-01-16 24:00", 400]]],
  #    ["2014-01-17", [["2014-01-17 00:00", 400], ["2014-01-17 12:00", 500],
  #      ["2014-01-17 24:00", 500]]],
  #    ["2014-01-18", [["2014-01-18 00:00", 500], ["2014-01-18 03:00", 600],
  #      ["2014-01-18 06:00", 700], ["2014-01-18 24:00", 700]]]]

现在我们只需要将每个元素(每个日期一个)映射到vals的加权平均值(请注意,我们不使用的每个元素的第一个元素enum):

enum.map { |_,arr| (arr.each_cons(2)
                       .reduce(0.0) { |t,((d1,v1),(d2,_))|
                          t + min_diff(d2,d1)*v1 }/1440.0).round(2) }
  #=> [100.0, 229.17, 450.0, 662.5]  

使用助手:

def min_diff(str1, str2)
  60*(str1[-5,2].to_i - str2[-5,2].to_i) + str1[-2,2].to_i - str2[-2,2].to_i 
end

放在一起:

arr1.chunk { |a| a.first[0,10] }
    .map { |_,arr| (arr.each_cons(2)
                       .reduce(0.0) { |t,((d1,v1),(d2,_))| 
                          t + min_diff(d2,d1)*v1 }/1440.0).round(2) }
  #=> [100.0, 229.17, 450.0, 662.5]  

和帮手一起min_diff

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将键数组映射到值数组

来自分类Dev

将 json 值映射到数组

来自分类Dev

Ruby:将字符串数组映射到数组数组

来自分类Dev

XML将简单的数据序列映射到复杂的数据数组

来自分类Dev

XML将简单的数据序列映射到复杂的数据数组

来自分类Dev

Ruby视图无法将值映射到布尔值

来自分类Dev

将数组对象值映射到新数组

来自分类Dev

ruby将函数映射到多个数组

来自分类Dev

ruby将函数映射到多个数组

来自分类Dev

将值映射到数组的通用解决方案

来自分类Dev

将NumPy数组条目映射到字典值

来自分类Dev

如何将Xml数组的值映射到csv字段

来自分类Dev

将值映射到数组对象中的键

来自分类Dev

使用递增的键名称将数组值映射到哈希

来自分类Dev

将数组的值作为参数映射到函数 PHP

来自分类Dev

将SwiftyJSON映射到数组

来自分类Dev

将时间序列数据映射到以前的数据点和平均值

来自分类Dev

将像素序列映射到其颜色

来自分类Dev

将数组部分映射到新数组

来自分类Dev

将索引数组映射到坐标数组

来自分类Dev

将数组映射到数组内部

来自分类Dev

将数组映射到对象数组

来自分类Dev

将数组映射到新数组

来自分类Dev

JSON反序列化-使用JSON.NET将数组索引映射到属性

来自分类Dev

将序列映射到数组时,Automapper返回对同一对象的引用

来自分类Dev

JSON反序列化-使用JSON.NET将数组索引映射到属性

来自分类Dev

如何使用敲除映射将null值映射到可观察的空数组?

来自分类Dev

将序列中的值映射到数据框中的所有元素

来自分类Dev

将值范围映射到单个值