有关快速性能扩展的建议适用于deedle

时间:2016-02-10 01:52:41

标签: f# deedle

Stats.expandingXXXX功能非常快。然而,没有公开的api来做扩展的Windows应用。我创建的以下解决方案在涉及像100k这样的大型数据集时非常慢。有什么建议值得赞赏吗?

 let ExpWindowApply f minSize data = 
        let keys = dataSeries.Keys
        let startKey = dataSeries.FirstKey()
        let values = keys
                     |> Seq.map(fun k -> 
                                    let ds = data.Between(startKey,k) 
                                    match ds with 
                                    |_ when ds.ValueCount >= minSize -> f ds.Values
                                    |_ -> Double.NaN
                                )                     
        let result = Series(keys, values)
        result

我理解Stats.expandingXXX函数实际上是特殊情况,其中应用的函数可以根据先前的循环状态进行迭代计算。并非所有功能都可以利用先前计算中的状态。在创建数据窗口方面,有没有比Series.Between更好的方法?

更新

对于那些对类似问题也感兴趣的人。答案为很少记录的系列向量和索引操作提供了替代实现和洞察力。但它并没有提高性能。

1 个答案:

答案 0 :(得分:2)

Deedle中的扩展函数很快,因为它们使用an efficient online algorithm,只需一次通过就可以实时计算统计数据 - 而不是实际构建子范围的中间序列。

有一个内置函数aggregate可以让你做一些事情 - 虽然它以相反的方式工作。例如,如果要将从当前元素开始到结尾的所有元素相加,可以写:

let s = series [ for i in 1 .. 10 -> i, float i ]

s |> Series.aggregateInto
        (Aggregation.WindowWhile(fun _ _ -> true))
        (fun seg -> seg.Data.FirstKey()) 
        (fun seg -> OptionalValue(Stats.sum seg.Data))

如果要使用基础表示执行相同的操作,可以直接使用Deedle用于将键(在索引中)与值(在数据向量中)链接的寻址方案。这是一个丑陋的可变样本,但你可以把它封装成更好的东西:

[ let firstAddr = s.Index.Locate(s.FirstKey())
  for k in s.Index.KeySequence ->
    let lastAddr = s.Index.Locate(k)
    seq { 
      let a = ref firstAddr
      while !a <> lastAddr do
        yield s.Vector.GetValue(!a).Value
        a := s.Index.AddressOperations.AdjustBy(!a, +1L) } |> Seq.sum ]