我已经使用创建了一个数据帧
// Create a dataframe containing the Open, High, Low, and Close
let ohlc =
cl
|> Frame.sliceCols ["Open"; "High"; "Low"; "Close"; "Volume"]
其结果输出为:打开-高-低关闭音量2014年12月28日8:00:00 PM->62.13 62.67 62.13 62.27 3206
2014年12月28日9:00:00 PM->62.27 62.42 62.14 62.39 1620
2014年12月28日10:00:00 PM->62.4 62.41 62.16 62.21 1275
2014年12月28日11:00:00 PM->62.21 62.32 61.96 62.19 2791
2014年12月29日12:00:00 AM->62.17 62.25 62.08 62.23 1233
2014年12月29日凌晨1:00->62.23 62.41 62.21 62.31 1186
2014年12月29日凌晨2:00->62.32 62.32 62.07 62.21 1446
2014年12月29日凌晨3:00->62.22 62.35 62.17 62.28 1335
我现在想从上面的每小时样本中生成一个更高的时间框架(每天)。
我从开始
ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)
其返回:Series<DateTime,Series<DateTime,ObjectSeries<string>>>.
我想创建一个新的DataFrame,包含Date(key)、Open、High、Low、Close和Volume列。Open是该系列第1行中的第一个Open。High是该系列中的最大High。Low是系列中的Min Low。Close是该系列的最后一个Close。Volume是系列中Volume的总和
所以类似于:
ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)
|> ??
|> ??
与其尝试使用"行"在"框架"级别执行此操作,不如尝试使用"列"在"帧"级别执行该操作?
更新这是完成的代码:
ohlc
|> Frame.rows
|> Series.resampleEquiv (fun d -> d.Date)
|> Series.mapValues (fun s ->
let temp = Frame.ofRows s
series ["Open" => Series.firstValue temp?Open
"High" => defaultArg (Stats.max temp?High) nan
"Low" => defaultArg (Stats.min temp?Low) nan
"Close" => Series.lastValue temp?Close
"Volume" => defaultArg (Some( Stats.sum temp?Volume) ) nan ] )
|> Frame.ofRows
我无法使用:
"Volume" => defaultArg (Stats.sum temp?Volume) nan ] )
因为这给了我一个错误消息:这个表达式应该有类型float选项,但这里有类型floast。我不得不包装函数Some()。不确定Stats.sum为什么需要,但Stat.max和Stats.min不需要。
调用resampleEquiv
后,您将得到一系列(表示具有相同日期的块)对象系列(表示原始帧的不同列)的系列(表示不同时间但相同日期的值)。
您可以在顶级系列上进行迭代,并将每个对象系列(每个块)返回到一个框架中。然后,您可以在帧上进行聚合,并返回一个新行:
source
|> Series.resampleEquiv (fun d -> d.Date.Year)
|> Series.mapValues (fun s ->
let temp = Frame.ofRows s
series [ "Open" => Series.firstValue temp?Open
"High" => defaultArg (Stats.max temp?High) nan ])
|> Frame.ofRows
我这样做只是为了公开赛和高中,但你可以看到这个想法:-)。对每个区块调用Frame.ofRows
也应该相当快,因为Deedle知道区块中的所有项目都有相同的索引。(或者,您可以对各个行进行迭代,但这会使其更长)。