Rube,Yahoo!中的时间序列转换管式

时间:2010-05-07 17:03:37

标签: ruby transform

我正在尝试构建一个系统,用于以编程方式过滤时间序列数据,并想知道这个问题是否已经解决,或者至少已经被黑客攻击过了。考虑到范围和传球能力,这似乎是一个完美的机会来做一些Ruby块魔法;但是,我仍然没有完全了解如何利用积木。

即便:

从我的数据库中提取数据,我可以创建一个哈希或一个数组,让我们使用数组:

data = [[timestamp0, value0],[timestamp1,value1], … [timestampN, valueN]]

然后我可以为数组添加一个方法,可能是这样的:

class Array
  def filter &block
    …
    self.each_with_index do |v, i|
      …
      # Always call with timestep, value, index
      block.call(v[0], v[1], i)
      …
    end
  end
end

我理解Ruby块的一个功能是传递的代码块发生在闭包范围内。所以以某种方式调用data.filter应该允许我使用该范围。我只能在不利用范围的情况下弄清楚如何做到这一点。即:

# average if we have a single null value, assumes data is correctly ordered
data.filter do |t, v, i|
  # Of course, we do some error checking…
  (data[i-1] + data[i+1]) / 2 if v.nil?
end

我想要做的实际上是(允许用户)以编程方式构建数学过滤器,但是一次一步,我们将构建一些函数:

def average_single_values(args)
  #average over single null values
  #return filterable array
end

def filter_by_std(args)
  #limit results to those within N standard deviations
  #return filterable array
end

def pull_bad_values(args)
  #delete or replace values seen as "bad"
  #return filterable array
end

my_filters == [average_single_values, filter_by_std, pull_bad_values]

然后,有了一个过滤器列表,我想(不知何故)我应该能够做到:

data.filter do |t, v, i|
  my_filters.each do |f|
    f.call t, v, i
  end
end

或者,假设一个不同的过滤器实现:

filtered_data = data.filter my_filters

这可能是设计它的更好方法,因为它返回一个新数组并且是非破坏性的

结果是一个已经遍历所有过滤器的数组。最终的目标是能够拥有可以通过任意过滤器运行的静态数据数组,以及可以像Yahoo!那样的方式作为对象传递(和共享)的过滤器。管道使用Feed进行管理。我现在不是在寻找太普遍的解决方案,我可以使数组的格式/返回严格。

有没有人在Ruby中看过类似的东西?或者有一些基本的指示?

1 个答案:

答案 0 :(得分:1)

关于在数组范围内工作的问题的前半部分似乎是不必要的,与您的问题无关。至于创建使用块操作数据的操作,可以使用Proc实例(“procs”),它们实际上是存储在对象中的块。例如,如果要使用名称存储它们,可以创建过滤器的哈希值:

my_filters = {}

my_filters[:filter_name] = lambda do |*args|
  # filter body here...
end

当然,您不需要为它们命名,并且可以使用数组。然后,要通过一系列有序过滤器运行某些数据,请使用有用的Enumerable#inject方法:

my_filters.inject(data) do |result, filter|
  filter.call result
end

它也没有使用monkeypatching!