Clojure:向量的惯用加权平均值

时间:2016-08-03 09:24:10

标签: 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 两个输入是加权版本。

i-partial就像是部分但fn已经颠倒了args

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

所以我的功能正常,没问题。 但在某种程度上,我想在一个更惯用的Clojure中实现它。

我尝试了很多像(map (fn [&xs ...这样的组合,但它不起作用。 是否可以采用未定义数量的向量的所有第n个元素并直接应用stats / mean?我的意思是单行

由于

编辑(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)))))

2 个答案:

答案 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)))))

答案 1 :(得分: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)

利润!