基于Deedle Row的计算

时间:2014-08-17 00:54:06

标签: f# deedle

我正在尝试使用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 )

如果有不同的方式请告诉我。希望这对像我这样的新人有用。

1 个答案:

答案 0 :(得分:3)

您使用f1.Rows的方法,将每一行投射到一个数字系列,然后应用Stats函数正是我建议的答案,所以我认为这种方法非常有意义。

我能想到的另一个选择是将帧转换为非规范化表示,然后按colacolb值对行进行分组(因此,您将拥有全部数据为行,但按其他属性分组):

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

我不确定我现在推荐哪种方法 - 这可能取决于您需要对数据执行的其他操作。但是考虑到替代方案是件好事。