F# 与列表相比,Deedle/Series的速度慢是正确的吗?
我正在开发一个数据“密集型”应用程序,我不确定是否应该使用Series./DataFrame。这看起来很有趣,但它看起来也比列表中的等效项慢很多。。。但我可能无法在过滤时正确使用该系列。 请让我知道你的想法 谢谢F# 与列表相比,Deedle/Series的速度慢是正确的吗?,f#,deedle,F#,Deedle,我正在开发一个数据“密集型”应用程序,我不确定是否应该使用Series./DataFrame。这看起来很有趣,但它看起来也比列表中的等效项慢很多。。。但我可能无法在过滤时正确使用该系列。 请让我知道你的想法 谢谢 type TSPoint<'a> = { Date : System.DateTime Value : 'a } type TimeSerie<'a> = TSPoint<'a> list let sd
type TSPoint<'a> =
{
Date : System.DateTime
Value : 'a
}
type TimeSerie<'a> = TSPoint<'a> list
let sd = System.DateTime(1950, 2, 1)
let tsd =[1..100000] |> List.map (fun x -> sd.AddDays(float x))
// creating a List of TSPoint
let tsList = tsd |> List.map (fun x -> {Date = x ; Value = 1.})
// creating the same as a serie
let tsSeries = Series(tsd , [1..100000] |> List.map (fun _ -> 1.))
// function to "randomise" the list of dates
let shuffleG xs = xs |> List.sortBy (fun _ -> Guid.NewGuid())
// new date list to search within out tsList and tsSeries
let d = tsd |> shuffleG |> List.take 1000
// Filter
d |> List.map (fun x -> (tsList |> List.filter (fun y -> y.Date = x)))
d |> List.map (fun x -> (tsSeries |> Series.filter (fun key _ -> key = x)))
类型TSPoint列表
设sd=System.DateTime(1950,2,1)
让tsd=[1..100000]|>List.map(funx->sd.AddDays(float x))
//创建TSPoint的列表
让tsList=tsd |>List.map(funx->{Date=x;Value=1.})
//创建与系列相同的
让tsSeries=Series(tsd,[1..100000]|>List.map(乐趣->1.))
//函数“随机”日期列表
让shuffleG xs=xs |>List.sortBy(fun |->Guid.NewGuid())
//要在out tsList和tsSeries中搜索的新日期列表
让d=tsd |>shuffleG |>List.take 1000
//滤器
d |>List.map(funx->(tsList |>List.filter(funy->y.Date=x)))
d |>List.map(fun x->(tsSeries |>Series.filter(fun key->key=x)))
以下是我得到的:
列表->实际:00:00:04.780,CPU:00:00:04.508,GC gen0:917,gen1:2,gen2:1
Series->Real:00:00:54.386,CPU:00:00:49.311,GC gen0:944,gen1:7,gen2:3一般来说,Deedle Series和数据帧比使用针对给定问题最有效的数据结构编写手工编写的代码有一些额外的开销。某些操作的开销较小,而某些操作的开销较大,因此这取决于您想做什么以及如何使用Deedle 如果您以预期的方式使用Deedle,那么您将获得良好的性能,但如果您运行大量效率不高的操作,则可能会获得较差的性能 在您的特定情况下,您正在1000系列上运行
Series.filter
,并创建一个新的系列(这是在幕后发生的)确实会有一些开销
但是,代码真正做的是使用Series.filter
查找具有特定键的值。Deedle为此提供了一个基于键的查找操作(这是它经过优化的原因之一)
如果您按照以下方式重写代码,那么使用Deedle将比使用list获得更好的性能:
d |> List.map (fun x -> tsSeries.[x])
// 0.001 seconds
d |> List.map (fun x -> (tsSeries |> Series.filter (fun key _ -> key = x)))
// 3.46 seconds
d |> List.map (fun x -> (tsList |> List.filter (fun y -> y.Date = x)))
// 40.5 seconds
tbh,列表本身将非常慢。根据你的使用情况考虑一个数组。但是数组是可变的,这是我不是一个巨大的风扇,只是不要突变它:Dthanks,我不认为这样做。我将使用TryGet,这样我会得到一个可选值,这样我就可以进行一些模式匹配,而不是得到一个异常(如果找不到该值)。@John_hk Yes,
TryGet
是一种方法,如果该键或值可能丢失!