2013-10-07 56 views
1

我有以下數據:組,和與加權平均F#

let data = [(41609.00 , 10000., 3.822); (41609.00, 60000., 3.857); (41974.00 , 20000., 4.723); (41974.00, 30000., 3.22); (41974.00 , 4000., 4.655); (42339.00, 7000., 4.22); (42339.00 , 5000., 3.33)] 

拳頭柱= OADate,第二=體積,第三=價格。

我現在想按日期分組,計算總量並計算加權平均價格。這是我到目前爲止:

let aggr data = 
    data 
    //Multiply second and third column element by element 
    |> Seq.map (fun (a, b, c) -> (a, b, b * c)) 
    //Group by first column 
    |> Seq.groupBy fst 
    //Sum column 2 & 3 based on group of column 1 
    |> Seq.map (fun (d, e, f) -> (d, e |> Seq.sum, f |> Seq.sum)) 
    //take the sum and grouped column 1 & 2 and compute weighted average of the third 
    |> Seq.map (fun (g, h, i) -> (g, h, i/h)) 

我得到一個類型不匹配的元組有不同的長度。我以前使用類似的語法沒有問題。 任何人都可以請我指出正確的方向?

UPDATE:

如果有人有興趣的解決方案是:多虧了托馬斯和葉

let aggr data = 
data 
|> Seq.map (fun (a, b, c) -> (a, b, b * c)) 
|> Seq.groupBy (fun (a, b, c) -> a) 
|> Seq.map (fun (key, group) -> group |> Seq.reduce (fun (a, b, c) (x, y, z) -> a, b+y , c+z)) 
|> Seq.map (fun (g, h, i) -> (g, h, i/h)) 
+0

可能會對此感興趣的相關問題:http://stackoverflow.com/q/2328697/11410 – Benjol

回答

3

在代碼中的第一個問題是,你正在呼籲Seq.groupByfst作爲參數。這不起作用,因爲fst是返回兩元素元組的第一個元素的函數,但是您的輸入是三元元組。遺憾的是,該功能對任何元組都不起作用。您需要編寫一個選擇三個中第一個值的lambda:

(...) 
|> Seq.groupBy (fun (a, b, c) -> a) 

接下來的問題是下一步的映射。分組產生一個元組列表,其中包含作爲第一個元素的鍵(time)和包含原始輸入序列中元素列表的組(在你的情況下是三元元組)。要與組中的所有第二組分的總和一起返回鍵,你可以寫:

(...) 
|> Seq.map (fun (key, group) -> key, group |> Seq.sumBy (fun (_, v, _) -> v)) 

我不能完全確定要與第二和第三列做什麼,但是這應該給你知道如何繼續。

+0

另外,我一直在研究時間序列和數據框操作的庫,這可能會使這更容易。如果您有興趣,請查看https://github.com/BlueMountainCapital/FSharp.DataFrame和http://bluemountaincapital.github.io/FSharp.DataFrame/。 –

+0

感謝Tomas。這是否意味着如果我想通過hte鍵來求和snd和trd列,我需要在兩行中做到這一點?此外,最後一個Seq.map也存在問題。任何想法? – nik

+0

你總是可以用多個鍵返回一個元組 - 在第二個片段中,我剛剛返回了組的鍵和值,但是你可以擴展它並返回其他東西(第三列的總和?)我認爲它應該工作一次你做吧。 –