0

给定一个框架:Frame<(string * int * int),int>

let df = 
  [ (("N1", 100,1), "C1", 1.0); (("N2",100,2), "C1", 3.1)
    (("N3",100,3), "C1", 4.0); (("N4",100,4), "C1", -6.4);
    (("N1", 200,5), "C2", 1.0); (("N2",200,6), "C2", 7.1)
    (("N3",200,7), "C2", 4.0); (("N4",200,8), "C2", -2.4);
    (("N1", 100,1), "C2", 1.0); (("N2",100,2), "C2", 5.1)
    (("N3",100,3), "C2", 4.0); (("N4",100,4), "C2", -8.4);
    (("N1", 200,5), "C1", 1.0); (("N2",200,6), "C1", 1.1)
    (("N3",200,7), "C1", 4.0); (("N4",200,8), "C1", -9.4)]
  |> Frame.ofValues

我希望能够按行键元组中的第二项对列进行分组 - 所以按 100 和 200 分组,然后将框架更改为Frame<(string*int),(int*int)>

似乎我必须使用Frame.Transpose然后Frame.groupRowsUsing对列进行分组,但我不知道如何在选择器函数中获得 100/200。

输出应如下所示:

        (100,C1)   (100,C2)     (200,C1)    (200,C2)
N1 1 -> 1           1           1           1   
N2 2 -> 3.1         5.1         1.1         7.1 
N3 3 -> 4           4           4           4   
N4 4 -> -6.4        -8.4        -9.4        -2.4     


4

1 回答 1

0

我不清楚是否打算保持列键不变并将行值更改为元组,或者列是否应该是元组并且值保持为浮点数。

假设第一个选项:

//adding a helper function to the module: transforms row data and replace a given columns
module Frame =
    let mapiReplaceCol col f frame = frame |> Frame.replaceCol col (Frame.mapRows f frame)

(df,df.ColumnKeys)
||> Seq.fold (fun acc elem ->
    acc |> Frame.mapiReplaceCol elem (fun (_,k,_) row -> k,row.GetAs<float>(elem)))
|> Frame.mapRowKeys (fun (a,_,c) -> a,c)

(*output:
            C1          C2          
N1 100 1 -> (100, 1)    (100, 1)    
N2 100 2 -> (100, 3.1)  (100, 5.1)  
N3 100 3 -> (100, 4)    (100, 4)    
N4 100 4 -> (100, -6.4) (100, -8.4) 
N1 200 5 -> (200, 1)    (200, 1)    
N2 200 6 -> (200, 1.1)  (200, 7.1)  
N3 200 7 -> (200, 4)    (200, 4)    
N4 200 8 -> (200, -9.4) (200, -2.4) 
*)

假设第二个选项:

第 1 步:将 Frame 解构为 (row * col * value) 并重建

let step1 =
    df |> Frame.mapRows (fun (a,b,c) row ->
        df.ColumnKeys |> Seq.map (fun col ->(a,c),(b,col),row.GetAs<float>(col)))
    |> Series.values |> Seq.concat |> Frame.ofValues
    
(*
output:
          100                 200                 
          C1        C2        C1        C2        
N1 1 -> 1         1         <missing> <missing> 
   5 -> <missing> <missing> 1         1         
N2 2 -> 3,1       5,1       <missing> <missing> 
   6 -> <missing> <missing> 1,1       7,1       
N3 3 -> 4         4         <missing> <missing> 
   7 -> <missing> <missing> 4         4         
N4 4 -> -6,4      -8,4      <missing> <missing> 
   8 -> <missing> <missing> -9,4      -2,4   
*)

第 2 步:降低级别

let step2 = step1 |> Frame.reduceLevel fst (fun (a : float) b -> a + b)

(*
output:
      100       200       
      C1   C2   C1   C2   
N1 -> 1    1    1    1    
N2 -> 3,1  5,1  1,1  7,1  
N3 -> 4    4    4    4    
N4 -> -6,4 -8,4 -9,4 -2,4 
*)

第 3 步(可选):重新创建索引中的元组

let step3 = step2 |> Frame.mapRowKeys (fun k -> k,k.Replace("N","") |> int)

(*
output:
        100       200       
        C1   C2   C1   C2   
N1 1 -> 1    1    1    1    
N2 2 -> 3,1  5,1  1,1  7,1  
N3 3 -> 4    4    4    4    
N4 4 -> -6,4 -8,4 -9,4 -2,4 
*)

基本上,我们从头开始重建框架。也许更好的方法是改变原始框架的构建方式,而不是做所有这些。

于 2020-05-04T16:32:04.460 回答