Melt和Cast是处理R中数据的流行操作。 在F#中,它将是相同类型或接近它的某些记录序列。
您是否了解F#中的任何此类功能?
(如果没有,谁会有兴趣制作一些强类型版本......)
更多信息:
Melt将表作为输入。 它有列标题(我们的记录字段)和一系列行。 这些列可以分为一组“标识符”和一组“变量”
Melt将此表放在一个新的规范形式中,列现在是: 标识符,名为@“variable”的列,名为@“value”的列
如果你原来有10个''变量',比如大小,重量等等,那么你将拥有每个以前的记录,规范形式的10条记录,@'变量'栏中的值被标题填充来自“变量”
的前几列相反,施放,从熔化的表中重建一张桌子。
R中的一个简短示例,melt
获取如下所示的数据(dat
):
a b c
1 1 0.48411551 0.2372291
2 2 0.58850308 0.3968759
3 3 0.74412592 0.9718320
4 4 0.93060118 0.8665092
5 5 0.01556804 0.2512399
并使它看起来像这样:
> melt(dat,id.vars = "a")
a variable value
1 1 b 0.48411551
2 2 b 0.58850308
3 3 b 0.74412592
4 4 b 0.93060118
5 5 b 0.01556804
6 1 c 0.23722911
7 2 c 0.39687586
8 3 c 0.97183200
9 4 c 0.86650918
10 5 c 0.25123992
cast
基本上是相反的。
这两项操作在日常工作中非常强大非常强大。 一旦你拥有它们就会改变你的想法,就像FP一样。
答案 0 :(得分:2)
假设melt
与SQL Server的unpivot
类似,这应该可以解决问题:
let melt keys (table: DataTable) =
let out = new DataTable()
let keyCols, otherCols =
table.Columns
|> Seq.cast<DataColumn>
|> Seq.toArray
|> Array.partition (fun c -> keys |> Seq.exists (fun k -> k = c.ColumnName))
for c in keyCols do
out.Columns.Add(c.ColumnName) |> ignore
out.Columns.Add("Key", typeof<string>) |> ignore
out.Columns.Add("Value") |> ignore
for r in table.Rows do
for c in otherCols do
let values = [|
for c in keyCols do yield r.[c]
yield box c.ColumnName
yield r.[c]
|]
out.Rows.Add(values) |> ignore
out
这是一个尝试它的小测试:
let table = new DataTable()
[|"Country", typeof<string>
"2001", typeof<int>
"2002", typeof<int>
"2003", typeof<int>|]
|> Array.map (fun (name, typ) -> new DataColumn(name, typ))
|> table.Columns.AddRange
[
"Nigeria", 1, 2, 3
"UK", 2, 3, 4
]
|> List.iter (fun (a, b, c, d) -> table.Rows.Add(a, b, c, d) |> ignore)
let table2 = table |> melt ["Country"]
table2.Rows
|> Seq.cast<DataRow>
|> Seq.iter (fun r ->
for (c: DataColumn) in table2.Columns do
printfn "%A: %A" c.ColumnName r.[c]
printfn "")
产生
"Country": "Nigeria"
"Key": "2001"
"Value": "1"
"Country": "Nigeria"
"Key": "2002"
"Value": "2"
...
假设cast
走另一条路(即pivot
),您应该可以使用此代码并提供翻译。
如果您正在执行此操作,您可能会发现将数据加载到SQL Server并使用内置运算符更容易。
答案 1 :(得分:0)
您是否了解F#中的任何此类功能?
F#标准库中没有这样的功能。
R
中的一个简短例子
你的示例数据可能用F#写成:
let header, data =
[ "a"; "b"; "c" ],
[ 1, 0.48411551, 0.2372291
2, 0.58850308, 0.3968759
3, 0.74412592, 0.9718320
4, 0.93060118, 0.8665092
5, 0.01556804, 0.2512399 ]
然后像这样“融化”:
let melt header data =
let header, data = Array.ofSeq header, Array.ofSeq data
[ header.[0], "variable", "value" ],
[ for a, b, c in data do
yield a, "b", b
yield a, "c", c ]
请注意,静态类型要求您的“b”和“c”列包含相同类型的值,因为它们已合并为单个列。
这两项行动每天都非常强大。一旦你拥有它们就会改变你的想法,就像FP一样。
我不明白为什么。我怀疑这是一个XY问题,你正在描述如何在使用F#中更有类型的方法更好地解决相同问题时如何解决问题,例如从“a”到从“变量”到“地图”的映射价值“但不知道任何人可能想要这些功能,我无法确定。