我正在开发一个数据“密集型”应用程序,并且不确定是否应该使用Series./DataFrame。看起来非常有趣,但是它看起来也比使用List进行的慢得多……但是我在过滤时可能没有正确使用Series。 请让我知道您的想法。
谢谢
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)))
这就是我得到的:
列表->实型:00:00:04.780,CPU:00:00:04.508,GC gen0:917,gen1:2,gen2:1
系列->实数:00:00:54.386,CPU:00:00:49.311,GC gen0:944,gen1:7,gen2:3
答案 0 :(得分:1)
通常,对于给定问题,Deedle系列和数据帧确实比使用最有效的数据结构编写手工编写的代码有一些额外的开销。对于某些操作而言,开销较小,而对于某些操作而言,开销较大,因此这取决于您要执行的操作以及使用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