2016-08-03 18 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)))))) 

次に

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

いくつかの注釈:

stats/meansは1または2の入力を受け取ります。
1つの入力バージョンのデフォルト値は1です。
2つの入力が加重バージョンです。

i-partialは、部分的に似ているが、FNが、だから私の関数の動作は問題を引数

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

を逆転していません。 しかし、私はそれをより慣用的なClojureで実装したいと思います。

(map (fn [&xs ...のようなもので多くの組み合わせを試しましたが、うまくいきません。 定義されていない数のベクトルのすべてのn番目の要素を取り、直接stats/meanを適用できますか?私はワンライナーに

感謝を意味

EDIT(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] [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) 

Profit!

+0

答えをいただきありがとうございます。私はあなたのロジックが厳しい場所を見ています。平均的な計算作業を行っているので、投稿を評価するのは難しいです。私はそれを私のmean-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

'(マップ(comp f1 f2 f3))'のマージで投稿を編集しました。 – birdspider

+0

私はゴルフを意味しませんでした。ちょうどこれを解決する私のバージョンを提案した。 – OlegTheCat

+0

ありがとう!私はちょうどapache-mathsラッパーであるために自分のfnを使っていました –