我想以惯用的方式计算向量的加权平均值。 为了说明我想要的东西,想象一下我有这些数据:
数据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)))))
答案 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)
利润!