我正在学习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:
  • 取框架
  • 使用Map键作为框架中的列名,
  • 处理值(<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=intV=float)
  • Frame<R, C>表示包含异类数据(每列可能具有不同类型)的帧,其中行由R索引,而列由C索引。对于通常被索引的框架R=int,通常,您的列将被命名为C=string(但是您也可以具有其他索引)
  • 10-02 15:00