ruby - 将值平均为一秒

时间:2015-04-01 03:48:37

标签: ruby csv time average

得到一个包含时间值的表,以毫秒为单位分辨率。是否有一种快速方法可以平均在一秒钟内发生所有值(操作后)?

输入表格

时间,价值

00:54:08.349,14

00:54:08.349,13

00:54:08.449,20

00:54:09.349,15

00:54:09.628,21

00:54:10.679,13

00:54:10.839,12

输出表格

时间,值

00:54:08.000,255(14 ^ 2 + 13 ^ 2 + 20 ^ 2)/ 3

00:54:09.000,333(15 ^ 2 + 21 ^ 2)/ 2

00:54:10.000,156.5(13 ^ 2 + 12 ^ 2)/ 2`

我正在将csv中的输入文件作为CSV::table阅读,因此每行都可以读为row[i] = csv[i]并且row[i]['time']row[i]['value']可用 - 有助于获得如何操纵它以获得平均值的想法。

1 个答案:

答案 0 :(得分:1)

这是一种方法,假设数组按时间排序,就像在示例中一样。

<强>代码

def avg_of_squares(a)
  a.chunk { |t,v| t[0,8] }.map { |t,v|
    [t[0,8], v.reduce(0) { |tot,(_,x)| tot + x*x }/(v.size.to_f)] }
end

如果未对a进行排序,请先在第一个元素上对其进行排序:

a.sort_by(&:first)

示例

a = [["00:54:08.349", 14],
     ["00:54:08.349", 13],
     ["00:54:08.449", 20],
     ["00:54:09.349", 15],
     ["00:54:09.628", 21],
     ["00:54:10.679", 13],
     ["00:54:10.839", 12]]

avg_of_squares(a)
  #=> [["00:54:08", 255.0], ["00:54:09", 333.0], ["00:54:10", 156.5]] 

<强>解释

步骤:

e = a.chunk { |t,v| t[0,8] }
  #=> #<Enumerator: #<Enumerator::Generator:0x007fbaac08a2f0>:each> 

将枚举数转换为数组以查看其内容:

e.to_a
  #=> [["00:54:08", [["00:54:08.349", 14], ["00:54:08.349", 13],
  #                  ["00:54:08.449", 20]]],
  #    ["00:54:09", [["00:54:09.349", 15], ["00:54:09.628", 21]]],
  #    ["00:54:10", [["00:54:10.679", 13], ["00:54:10.839", 12]]]]

f = e.map
  #=> #<Enumerator: #<Enumerator: #
  #    <Enumerator::Generator:0x007fbaac08a2f0>:each>:map> 
f.to_a
  # (same as for e)

您可以将f视为“复合枚举器”。将f的第一个元素传递给块并分配块变量:

t,v = f.next
  #=> ["00:54:08", [["00:54:08.349", 14], ["00:54:08.349", 13],
  #   ["00:54:08.449", 20]]] 
t 
  #=> "00:54:08" 
v
  #=> [["00:54:08.349", 14], ["00:54:08.349", 13], ["00:54:08.449", 20]]
g = v.reduce(0) { |tot,(_,x)|tot + x*x }/(v.size.to_f)
  #=> 255.0

所以f的第一个元素映射到:

["00:54:08", 255.0]

其他计算也是类似的。