gpt4 book ai didi

visual-studio-2015 - 如何在 F# 中优雅地操作这个 Deedle.Frame

转载 作者:行者123 更新时间:2023-12-01 00:35:19 31 4
gpt4 key购买 nike

我一直在努力使用 F#,尤其是使用 Deedle.Frame 和 Deedle.Series。

  • 我需要创建两个新列,其值取决于其他列。
  • 对于某些行,我需要插入一个新行。

  • 我目前的解决方案非常难看,基本上根据每个 if 语句过滤 Frame 并返回一个仅包含新列的新 Frame 。然后我将其合并到原始框架中。这工作自案件或互斥。我需要插入新行的情况是这样的,我将重新索引新框架,以便在合并期间将它简单地附加到原始框架的底部(最后一行之后)。

    然而,由于不同的 if-cases/patterns 很多,我必须处理大量的帧合并并确保处理 IF 语句的补充(否则会有缺失值)。

    Input Frame -> Target Frame (row order not important)
    // ****** PSEUDO CODE ******
    // Create new columns as copies.
    Add column ["NEWTYPE"] = ["TYPE"]
    Add column ["NEWVALUE"] = ["VALUE"]
    // Iterate over rows.
    foreach row in table
    IF row["GROUP"] == A
    typeParts = row["TYPE"].Split('/')
    // Swap order X/Y -> Y/X.
    IF typeParts[0] == "X" && typeParts[1] != "X"
    row["NEWTYPE"] = typeParts[1] + "/" + "X"
    row["NEWVALUE"] = row["VALUE"] / 10.0
    // Split row into two rows Z/Y -> {Z/X, Y/X}.
    ElseIF typeParts[0] != "X" && typeParts[1] != "X"
    Insert extraRow = row
    extraRow["NEWTYPE"] = typeParts[0] + "/" + "X"
    extraRow.["NEWVALUE"] = row["VALUE"] * 2.0
    row["NEWTYPE"] = typeParts[1] + "/" + "X"
    row["NEWVALUE"] = row["VALUE"] * 3.0
    ELSE
    // Do nothing, new columns already copied.
    ELSE
    // Do nothing, new columns already copied.

    任何能够想出一个好的解决方案的人的金星。我想它可以通过返回一个框架列表来解决(因为可能会创建一个新行)然后展平和合并所有?
    ***** 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

    最佳答案

    我会尝试这样的事情

    首先定义几个类型,使东西更容易处理

    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()

    定义变换函数。
    诀窍是这个函数返回一个列表 Target对象。要么有一个项目,要么有 2 个项目。
    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]

    最后通过 map 抽取您的列表和来源,最后连接这些列表
    xs
    |> List.map transform
    //will give you a List<List<Target>>
    |> List.concat

    关于visual-studio-2015 - 如何在 F# 中优雅地操作这个 Deedle.Frame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41718576/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com