2016-08-03 45 views
0

我想以慣用的方式計算向量的加權平均值。 爲了說明我想要的,想象我有這樣的數據:Clojure:向量的慣用加權平均值

數據1 = [2 1],1重量= 1個 數據2 = [3 4],2重量= 2

然後平均值= [ (2 * 1 + 3 * 2)/(1 + 2)(1 * 1 + 2 * 4)/(1 + 2)] = [2.67 3.0]

這是我的代碼:

(defn meanv 
    "Returns the vector that is the mean of input ones. 
    You can also pass weights just like apache-maths.stats/mean" 
    ([data] 
    (let [n (count (first data))] 
    (->> (for [i (range 0 n)] 
      (vec (map (i-partial nth i) data))) 
      (mapv stats/mean)))) 
    ([data weights] 
    (let [n (count (first data))] 
    (->> (for [i (range 0 n)] 
      (vec (map (i-partial nth i) data))) 
      (mapv (i-partial stats/mean weights)))))) 

Then

(meanv [[2 1] [3 4]] [1 2]) = [2.67 3.0] 

幾點說明:

stats/means需要1或2個輸入。
默認情況下,一個輸入版本的權重= 1。
兩個輸入是加權版本。

i-partial像部分,但FN發生了逆轉ARGS

Ex : ((partial/2) 1) = 2 
    ((i-partial/2) 1 = 1/2 

所以我的函數的工作,沒有任何問題。 但在某種程度上,我想用更習慣的Clojure來實現它。

我嘗試了許多與(map (fn [&xs ...之類的組合,但它不起作用。 是否有可能採取矢量的未定義數量的所有第n個元素,並直接應用統計/平均值?我的意思是一個班輪

感謝

編輯(birdspider答案)

(defn meanv 
    ([data] 
    (->> (apply mapv vector data) 
     (mapv stats/mean))) 
    ([data weights] 
    (->> (apply mapv vector data) 
     (mapv (i-partial stats/mean weights))))) 

而且隨着

(defn transpose [m] 
    (apply mapv vector m)) 

(defn meanv 
    ([data] 
    (->> (transpose data) 
     (mapv stats/mean))) 
    ([data weights] 
    (->> (transpose data) 
     (mapv (i-partial stats/mean weights))))) 
+0

爲什麼兩個數據除以(1 + 2)?? – birdspider

+0

nvm,它被除以權重的總和 – birdspider

+0

我很困惑 - 在你的文本描述中你說數據是'[[2 1] [3 4]]'權重是'[1 2]' - 在你使用的示例中'[[1 2] [3 4]]' - 那它是哪一個? – birdspider

回答

0

你想要做的第一件事是轉置矩陣(獲得第一,秒,三分之一等)

this SO頁面。

; https://stackoverflow.com/a/10347404/2645347 
(defn transpose [m] 
    (apply mapv vector m)) 

然後我會這樣做,輸入檢查完全缺席。

(defn meanv 
    ([data] 
    ; no weigths default to (1 1 1 ... 
    (meanv data (repeat (count data) 1)))) 
    ([data weigths] 
    (let [wf (mapv #(partial * %) weigths) ; vector of weight mult fns 
     wsum (reduce + weigths)] 
    (map-indexed 
     (fn [i datum] 
     (/ 
     ; map over datum apply corresponding weight-fn - then sum 
     (apply + (map-indexed #((wf %1) %2) datum)) 
     wsum)) 
     (transpose data))))) 

(meanv [[2 1] [3 4]] [1 2]) => (8/3 3) ; (2.6666 3.0) 

利潤!

+0

感謝您的回答,我知道您的邏輯難度在哪裏,因爲它的平均計算工作很難評估您的帖子。我會嘗試將它與我的意思-fn合併,看看它是否更好! –

+0

好吧,我試過了,顯然更好!因爲我們在打高爾夫球,所以編輯我的帖子合併 –

1
(def mult-v (partial mapv *)) 
(def sum-v (partial reduce +)) 
(def transpose (partial apply mapv vector)) 

(defn meanv [data weights] 
    (->> data 
     transpose 
     (map (partial mult-v weights)) 
     (map sum-v) 
     (map #(/ % (sum-v weights))))) 
+0

'(map(comp f1 f2 f3))' – birdspider

+0

我不是打高爾夫的意思。剛剛提出瞭解決這個問題的版本。 – OlegTheCat

+0

也謝謝!我只是用我自己的fn表示這是一個apache數學包裝 –