平均一个大阵列?

时间:2013-03-20 13:38:33

标签: ruby arrays postgresql average

我最终得到了大量的数字(从数据库中提取)。

所以,它可能看起来像:[1,3,1,2,1,3,1,2,3,1,2,3,1,3,1,3,1,1,3,2,3,3,3,3,1,1,1,1,3,2,1]

除了它可能是50,000个数字而不是几十个。最低的数字始终为1,最高的数字为3

我需要做的是找到某种滚动平均值,以便我可以在可管理的折线图中显示数据。

那么可能平均每5-10个数据点的数量?只是不确定处理这样的事情的最佳方法是什么。

注意:不希望获得单一平均值。我希望将整个阵列提炼成几个平均点。因此,1000点的数据集可能会被分解为10个平均数。

3 个答案:

答案 0 :(得分:4)

1.9.3p327 :001 > a = [1,3,1,2,1,3,1,2,3,1,2,3,1,3,1,3,1,1,3,2,3,3,3,3,1,1,1,1,3,2,1]
 => [1, 3, 1, 2, 1, 3, 1, 2, 3, 1, 2, 3, 1, 3, 1, 3, 1, 1, 3, 2, 3, 3, 3, 3, 1, 1, 1, 1, 3, 2, 1]
1.9.3p327 :002 > a.each_cons(10).map { |subarray| subarray.reduce(0.0, :+) / subarray.size }
 => [1.8, 1.9, 1.9, 1.9, 2.0, 2.0, 2.0, 2.0, 1.9, 1.9, 2.0, 2.1, 2.1, 2.3, 2.3, 2.3, 2.1, 2.1, 2.1, 2.1, 2.1, 1.9]

但这在性能方面并不好。它是O(NM),其中N是数组的大小,M是窗口的大小(在这种情况下为10)。

UPD:或者你可以使用each_slice,如果你需要“减少”数组大小:

1.9.3p327 :002 > a.each_slice(10).map { |subarray| subarray.reduce(0.0, :+) / subarray.size }
 => [1.8, 2.0, 2.1, 1.0]

答案 1 :(得分:4)

可以通过数据库选择直接获取此切片平均值。您的数据库引擎几乎肯定会进行分组和平均计算至少比ruby快一个数量级,此外,您将通过线路将更少的数据从数据库传输到您的程序,并大大减少在您的实例中实例化的对象数量ruby程序代表结果集。

因此,如果您的原始查询看起来像这样(在Postgresql中):

select value from mytable;

你可以修改它以产生平均每十个项目,如:

select avg(value) as chunk_avg, row/10 as chunk
from 
  (select value, row_number() over () - 1 as row
   from mytable) x
group by chunk
order by chunk;

SqlFiddle

如果您不想在结果中使用块编号,可以将其包装在另一个仅投影chunk_avg的外部选择中,或从chunk子句中删除select字段并在chunkrow/10子句中将group by替换为order by

答案 2 :(得分:1)

平均值 NOT 与整体平均值相同。除非你不要求太高的精确度,或者不需要平均子集,否则我不推荐它。