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更好的方法?
更新
对于那些对类似问题也感兴趣的人。答案为很少记录的系列向量和索引操作提供了替代实现和洞察力。但它并没有提高性能。
答案 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 ]