Visual studio 2015 我如何优雅地操纵F中的这个框架#

Visual studio 2015 我如何优雅地操纵F中的这个框架#,visual-studio-2015,f#,deedle,Visual Studio 2015,F#,Deedle,我一直在与F#作斗争,尤其是与Deedle.Frame和Deedle.Series一起工作 我需要创建两个新列,其值依赖于其他列 对于某些行,我需要插入新行 我目前的解决方案非常难看,基本上是根据每个if语句过滤框架,然后返回一个只包含新列的新框架。然后,我将其合并到原始帧中。这起作用的案例或相互排斥。当我需要插入新行时,我将重新为新帧编制索引,以便在合并过程中只需将其附加到原始帧的底部(最后一行之后) 但是,由于不同的if情况/模式很多,我必须处理大量的帧合并,并确保if语句的补码得到处理(否

我一直在与F#作斗争,尤其是与Deedle.Frame和Deedle.Series一起工作

  • 我需要创建两个新列,其值依赖于其他列
  • 对于某些行,我需要插入新行
  • 我目前的解决方案非常难看,基本上是根据每个if语句过滤框架,然后返回一个只包含新列的新框架。然后,我将其合并到原始帧中。这起作用的案例或相互排斥。当我需要插入新行时,我将重新为新帧编制索引,以便在合并过程中只需将其附加到原始帧的底部(最后一行之后)

    但是,由于不同的if情况/模式很多,我必须处理大量的帧合并,并确保if语句的补码得到处理(否则将丢失值)

    对任何能够想出好的解决方案的人来说都是一颗金星。我想可以通过返回一个帧列表(因为可能会创建一个新行)然后展平并合并所有帧来解决这个问题

    ***** Here is my current ugly F# code: *****
    
    let subA =
        inputFrame
        |> Frame.filterRowValues(fun row -> row.GetAs<string>("GROUP") = "A")
    
    let grpSwap =
        subA 
        |> Frame.filterRowValues(fun row -> 
            let typeParts = row.GetAs<string>("TYPE").Split('/')
            typeParts.[0] = "X" && typeParts.[1] <> "X")
        |> Frame.mapRowValues(fun r -> 
            let typeParts = r.GetAs<string>("TYPE").Split('/')
            series ["NEWTYPE" => box (typeParts.[1] + "/" + typeParts.[0]); "NEWVALUE" => box (r.GetAs<float>("VALUE") / 10.0)])
        |> Frame.ofRows
    
    let grpCopy =
        subA 
        |> Frame.filterRowValues(fun row -> 
            let typeParts = row.GetAs<string>("TYPE").Split('/')
            typeParts.[0] <> "X" && typeParts.[1] = "X")
        |> Frame.mapRowValues(fun r -> 
            series ["NEWTYPE" => box (r.GetAs<string>("TYPE")); "NEWVALUE" => box (r.GetAs<float>("VALUE"))])
        |> Frame.ofRows
    
    
    let rowsToSplit =
        subA 
        |> Frame.filterRowValues(fun row -> 
            let typeParts = row.GetAs<string>("TYPE").Split('/')
            typeParts.[0] <> "X" && typeParts.[1] <> "X")
    
    let grpSplit1 =
        rowsToSplit 
        |> Frame.mapRowValues(fun r -> 
            let typeParts = r.GetAs<string>("TYPE").Split('/')
            series ["NEWTYPE" => box (typeParts.[0] + "/" + "X"); "NEWVALUE" => box (r.GetAs<float>("VALUE") * 2.0)])
        |> Frame.ofRows
    
    let grpSplit2 =
        rowsToSplit
        |> Frame.mapRowValues(fun r -> 
            let typeParts = r.GetAs<string>("TYPE").Split('/')
            series ["NEWTYPE" => box (typeParts.[1] + "/" + "X"); "NEWVALUE" => box (r.GetAs<float>("VALUE") * 3.0)])
        |> Frame.ofRows
    
    let grpAComplement =
        inputFrame 
        |> Frame.filterRowValues(fun row -> 
            row.GetAs<string>("GROUP") <> "A")
        |> Frame.mapRowValues(fun r -> 
            series ["NEWTYPE" => box (r.GetAs<string>("TYPE")); "NEWVALUE" => box (r.GetAs<float>("VALUE"))])
        |> Frame.ofRows
    
    
    let outputFrame = 
        let final0 = Frame.mergeAll([inputFrame; grpSwap; grpCopy; grpSplit1; grpAComplement])
        let appendFromIndex = (final0.RowCount)
        let appendToIndex = appendFromIndex + (grpSplit2.RowCount-1)
        let newRow = grpSplit2 |> Frame.merge rowsToSplit
        newRow |> Frame.indexRowsWith [appendFromIndex..appendToIndex] |> Frame.merge final0
    
    ****这是我目前的丑陋F#代码:*****
    让苏巴=
    输入框
    |>Frame.filterRowValues(有趣的行->行.GetAs(“组”)=“A”)
    让grpSwap=
    苏巴
    |>Frame.filterRowValues(有趣的行->
    让typeParts=row.GetAs(“TYPE”).Split(“/”)
    类型部件。[0]=“X”和类型部件。[1]“X”)
    |>Frame.mapRowValues(乐趣r->
    设typeParts=r.GetAs(“TYPE”).Split(“/”)
    系列[“NEWTYPE”=>box(typeParts[1]+“/”+typeParts[0]);“NEWVALUE”=>box(r.GetAs(“VALUE”)/10.0)])
    |>路框
    让GRP复印=
    苏巴
    |>Frame.filterRowValues(有趣的行->
    让typeParts=row.GetAs(“TYPE”).Split(“/”)
    类型部件。[0]“X”和&typeParts。[1]=“X”)
    |>Frame.mapRowValues(乐趣r->
    系列[“NEWTYPE”=>box(r.GetAs(“TYPE”);“NEWVALUE”=>box(r.GetAs(“VALUE”))]
    |>路框
    让我们分手吧=
    苏巴
    |>Frame.filterRowValues(有趣的行->
    让typeParts=row.GetAs(“TYPE”).Split(“/”)
    类型部件。[0]“X”和类型部件[1]“X”)
    让grpSplit1=
    罗斯托斯普利特
    |>Frame.mapRowValues(乐趣r->
    设typeParts=r.GetAs(“TYPE”).Split(“/”)
    系列[“NEWTYPE”=>box(typeParts[0]+“/”+“X”);“NEWVALUE”=>box(r.GetAs(“VALUE”)*2.0)])
    |>路框
    让grpSplit2=
    罗斯托斯普利特
    |>Frame.mapRowValues(乐趣r->
    设typeParts=r.GetAs(“TYPE”).Split(“/”)
    系列[“NEWTYPE”=>box(typeParts.[1]+“/”+“X”);“NEWVALUE”=>box(r.GetAs(“VALUE”)*3.0)])
    |>路框
    让grpAComplement=
    输入框
    |>Frame.filterRowValues(有趣的行->
    第三行:GetAs(“集团”)“A”)
    |>Frame.mapRowValues(乐趣r->
    系列[“NEWTYPE”=>box(r.GetAs(“TYPE”);“NEWVALUE”=>box(r.GetAs(“VALUE”))]
    |>路框
    让outputFrame=
    设final0=Frame.mergeAll([inputFrame;grpSwap;grpCopy;grpSplit1;grpAComplement])
    让appendFromIndex=(final0.RowCount)
    设appendToIndex=appendFromIndex+(grpSplit2.RowCount-1)
    设newRow=grpSplit2 |>Frame.merge rowsToSplit
    newRow |>Frame.indexrow与[appendFromIndex..appendToIndex]|>Frame.merge final0
    
    我想试试这样的东西

    首先定义一些类型,使内容更易于处理

    type Group = 
        | A
        | B
        | C
    
    type Source = {
        Group: Group
        Typ: string
        Value: float
    }          
    
    type Target = {
        Group: Group
        Typ: string
        Value: float
        NType: string
        NValue: float
    }          
    
    创建并初始化初始列表

    let xs : List<Source> = createFromWhereEver()
    
    最后通过地图输入你的列表和来源,最后对这些列表进行压缩

    xs
    |> List.map transform
    //will give you a List<List<Target>>
    |> List.concat
    
    xs
    |>List.map变换
    //我会给你一份清单
    |>List.concat
    
    编写一个
    fromFrame::Frame->Source
    函数和一个
    toFrame::Target->Frame
    函数。然后将它们放在我下面描述的过程的开头和结尾
    xs |>List.map fromFrame>>transform |>List.concat |>List.map toFrame
    Nice!可能是我不知道列的确切数目/名称,除了上面使用的那些。如果这些可以简单地跟随,那就太好了。我想这会大大改变方法。我想这会让解决方案更难看?:)为什么会这样?当然,您可以直接使用
    Frame
    对象(如果有这样的东西-我不知道Deedle)。或者创建某种类型的适配器类型以在
    框架
    对象上分层我认为我的解决方案的真正诀窍很简单:使用
    映射
    的一些变体和一个处理函数,而不是返回
    类型
    总是返回
    列表
    。包含1个元素(原始元素)或多个元素的列表,具体取决于您的检查。然后再看那张名单。
    let transform (x:Source) : List<Target> =
        if x.Group = A then
            let init x ntype nvalue =
                {
                    Group = x.Group
                    Typ = x.Typ
                    Value = x.Value
                    NType = ntype
                    NValue = nvalue
                }
            let tp0 :: tp1 :: _ = x.Typ.split('/')
            // Swap order X/Y -> Y/X.
            if tp0 = "X" && tp1 <> "X" then
                [init x (tp1 + "/X") (x.value / 10)]
            // Split row into two rows Z/Y -> {Z/X, Y/X}.
            elif tp0 <> "X" && tp1 <> "X"
                [
                    init x (tp0 + "/X") (x.value * 2)
                    init x (tp1 + "/X") (x.value * 3)
                ]
            else
                [x]
        else
            [x]
    
    xs
    |> List.map transform
    //will give you a List<List<Target>>
    |> List.concat