我正在尝试使用Deedle进行基于行的计算。但是大多数例子都是基于列的。例如,我有这个简单的结构:
let tt = Series.ofObservations[ 1=>10.0; 3=>20.0;5=> 30.0 ]
let tt2 = Series.ofObservations[1=> 10.0; 3=> Double.NaN; 6=>30.0 ]
let f1 = frame ["cola" => tt; "colb"=>tt2]
val f1 : Frame<int,string> =
cola colb
1 -> 10 10
3 -> 20 <missing>
5 -> 30 <missing>
6 -> <missing> 30
我想计算可乐和colb的平均值。如果我做
f1.Rows |> Series.mapValues(fun r -> (r.GetAs<float>("cola") + r.GetAs<float>("colb") )/2.0)
val it : Series<int,float> =
1 -> 10
3 -> <missing>
5 -> <missing>
6 -> <missing>
我知道我可以匹配每一列来处理均值,但是如果有很多列,这将是不切实际的。
f1.Rows返回的每一行都是一个ObjectSeries,可以将它转换为float系列并将stats.mean应用到一行吗?
感谢 casbby
更新
我想我可能已经找到了其中一种方法(参考:https://github.com/BlueMountainCapital/Deedle/issues/100):
折叠操作:
f1.Rows |> Series.mapValues(fun v -> v.As<float>() |> Series.foldValues (fun acc elem -> elem + acc) 0.0 )
表示(它正确跳过缺失值):
f1.Rows |> Series.mapValues(fun v -> v.As<float>() |> Stats.mean )
数:
f1.Rows |> Series.mapValues(fun v -> v.As<float>() |> Stats.count )
如果有不同的方式请告诉我。希望这对像我这样的新人有用。
答案 0 :(得分:3)
您使用f1.Rows
的方法,将每一行投射到一个数字系列,然后应用Stats
函数正是我建议的答案,所以我认为这种方法非常有意义。
我能想到的另一个选择是将帧转换为非规范化表示,然后按cola
和colb
值对行进行分组(因此,您将拥有全部数据为行,但按其他属性分组):
let byCol =
f1
|> Frame.stack
|> Frame.groupRowsByString "Column";;
这会给你:
Row Column Value
cola 0 -> 1 cola 10
2 -> 3 cola 20
3 -> 5 cola 30
colb 1 -> 1 colb 10
4 -> 6 colb 30
现在,您可以使用处理分层索引的函数来执行计算。例如,要计算两组的Value
的平均值,您可以写:
byCol?Value |> Stats.levelMean fst
我不确定我现在推荐哪种方法 - 这可能取决于您需要对数据执行的其他操作。但是考虑到替代方案是件好事。