使用deedle快速扩展性能的建议
Suggestion for fast performance expanding apply with deedle
Stats.expandingXXXX
函数非常快。但是,没有 public api 来应用 expandingWindow。当涉及到像 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 函数实际上是特殊情况,应用的函数可以根据先前循环的状态迭代计算。并非所有功能都可以利用先前计算的状态。在创建 window 数据方面,有什么比 Series.Between 更好的方法吗?
更新
对于同样对类似问题感兴趣的人。答案提供了替代实现和对很少记录的序列向量和索引操作的洞察。但它并没有提高性能。
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 使用的寻址方案来 link 具有值(在数据向量中)的键(在索引中)。这是一个丑陋的可变样本,但您可以将其封装成更好的东西:
[ 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 ]
Stats.expandingXXXX
函数非常快。但是,没有 public api 来应用 expandingWindow。当涉及到像 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 函数实际上是特殊情况,应用的函数可以根据先前循环的状态迭代计算。并非所有功能都可以利用先前计算的状态。在创建 window 数据方面,有什么比 Series.Between 更好的方法吗?
更新
对于同样对类似问题感兴趣的人。答案提供了替代实现和对很少记录的序列向量和索引操作的洞察。但它并没有提高性能。
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 使用的寻址方案来 link 具有值(在数据向量中)的键(在索引中)。这是一个丑陋的可变样本,但您可以将其封装成更好的东西:
[ 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 ]