我正在学习F#。
我正在尝试将Map<string, seq<DateTime * float>>
转换为Deedle数据帧(http://bluemountaincapital.github.io/Deedle/tutorial.html#creating)。
我已经完成了以下代码:
let folderFnct (aFrame:Frame) colName datesAndValues =
let newSerie = Series(Seq.map (fun x -> fst x) datesAndValues, Seq.map (fun y -> snd y) datesAndValues)
let newFrame = aFrame.Join([colName], [newSerie], kind=JoinKind.Inner)
newFrame
let mapToDeedleFrame myMap frame =
Map.fold ( fun s ticker datesAndValues -> folderFnct s ticker datesAndValues) frame myMap
mapToDeedleFrame
使用现有框架折叠 map 。文件夹函数folderFnct
:<DateTime * float>
)使其成为一系列值。 问题在于:
let newFrame = aFrame.Join([colName], [newSerie], kind=JoinKind.Inner)
哪里:
未定义字段,构造函数或成员“Join”
我已经确定了此问题的三个潜在原因:
aFrame.Join
?我尝试显式指定aFrame
mapToDeedleFrame
? folderFnct
为空的情况在aFrame
中进行模式匹配? 非常感谢!
编辑1
根据Tomas的建议,这是我到目前为止提出的内容。
let folderFnct (aFrame:Frame<'a, 'b>) columnName (seqOfTuples: seq<'a*'b>) =
let newSerie = Series(Seq.map (fun x -> fst x) seqOfTuples, Seq.map (fun y -> snd y) seqOfTuples)
let otherFrame = Frame([columnName], [newSerie])
let newFrame = aFrame.Join((otherFrame), kind=JoinKind.Inner)
newFrame
let mapToDeedleFrame myMap frame =
Map.fold ( fun state k vals -> folderFnct state k vals) frame myMap
缺少的最后一步是:如何快速将空框架(可能避免创建虚拟框架)传递给
mapToDeedleFrame
?我已经尝试过[]
let frame = mapToDeedleFrame mapTS []
这可能是一个愚蠢的问题,但是我是F#的新手,我想知道是否在该语言中构建了
Empty
类型。关注问题
在源文件中,我读到了(https://github.com/BlueMountainCapital/Deedle/blob/master/src/Deedle/Frame.fs):
member frame.Join<'V>(colKey, series:Series<'TRowKey, 'V>, kind, lookup) =
let otherFrame = Frame([colKey], [series])
frame.Join(otherFrame, kind, lookup)
在屏幕上弹出功能说明时:
从上面的图片中,我猜想出Frame的类型与colKey相同,而据我所知,colKey只是随意向连接添加的dataframe列的键。作为一个完整的菜鸟,我很困惑。
编辑2
我已经重写了代码:
let seriesListMapper (colName:string, series:Series<'a, 'b>) =
[colName => series] |> frame
let frameListReducer (accFrame: Frame<'a, 'b>) (aFrame: Frame<'a, 'b>) =
accFrame.Join(aFrame, kind=JoinKind.Outer)
let seriesListToFrame (seriesList: List<string * Series<'a, 'b>>) =
seriesList |> List.map (fun elem -> seriesListMapper elem) |> List.reduce(fun acc elem -> frameListReducer acc elem)
问题是:
let frame = seriesListToFrame seriesList
返回frame作为Frame,而seriesList改为
(string *Series<DateTime, float>) list
我认为问题在于:
let seriesListMapper (colName:string, series:Series<'a, 'b>) =
[colName => series] |> frame
实际上
seriesListMapper
表示为seriesListMapper: colName:string * series:Series<'a, 'b> -> Frame<'a, string>
我不明白如何以及为什么将值从
string
转换为float
。一件有趣的事是,使用
frame.Format()
绘制框架实际上可以确认数据看起来正确。只是这种“奇怪的”转换为string
。 最佳答案
在folderFnct
的类型注释中,您具有aFrame:Frame
。但是,表示数据帧的类型是具有两个类型参数的泛型类型(分别表示行和列的索引类型),因此注释应为aFrame:Frame<_, _>
。
将序列添加到框架的另一种方法是使用变异操作:
aFrame.AddSeries(colName, newSeries)
但是,这仅支持左连接(只能通过添加新系列来突变数据框,但不能以更改索引的方式来对其进行更改)。但是,您可能可以使用此方法,然后在构建框架后从框架中删除所有丢失的值。
编辑:要回答有关泛型类型的问题:
Series<K, V>
用K
类型的键表示包含V
类型的值的序列(例如,具有通常索引的观测值的序列将具有K=int
和V=float
)Frame<R, C>
表示包含异类数据(每列可能具有不同类型)的帧,其中行由R
索引,而列由C
索引。对于通常被索引的框架R=int
,通常,您的列将被命名为C=string
(但是您也可以具有其他索引)