Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In clojure, what is an efficient way to calculate average of integer vectors

Tags:

clojure

matlab

I have:

(def data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]])

I want to average these (element-wise to get):

[3 6 5 5 6]

Like you would in MATLAB:

mean([1 3 4 7 9; 7 6 3 2 7; 1 9 8 6 2])

With Incanter I can do:

(map #(/ % (count m)) (apply plus data))

If data is rather large (and I have lots of them) is there a better way to do this?
Does it help to calculate the (count m) beforehand?
Does it help to defn the #(/ % (count m)) beforehand?

like image 464
Ali Avatar asked Nov 20 '11 23:11

Ali


2 Answers

Here's a pretty clean and simple way to do it:

(def data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]])

(defn average [coll] 
  (/ (reduce + coll) (count coll)))

(defn transpose [coll]
   (apply map vector coll))

(map average (transpose data))
=> (3 6 5 5 6)
like image 82
mikera Avatar answered Nov 23 '22 06:11

mikera


Without knowing how to use any of incanter, here's how you could do this "from scratch".

(let [data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]]
      num (count data)]
  (apply map (fn [& items]
               (/ (apply + items) num))
         data))

;=> (3 6 5 5 6)
like image 43
amalloy Avatar answered Nov 23 '22 07:11

amalloy