Visual studio 2015 我如何优雅地操纵F中的这个框架#
我一直在与F#作斗争,尤其是与Deedle.Frame和Deedle.Series一起工作Visual studio 2015 我如何优雅地操纵F中的这个框架#,visual-studio-2015,f#,deedle,Visual Studio 2015,F#,Deedle,我一直在与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