2011-11-20 13 views
6

tengo:En clojure, lo que es una forma eficiente para calcular la media de los vectores enteros

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

Quiero promediar estos (elemento a elemento de conseguir):

[3 6 5 5 6] 

Al igual que lo haría en MATLAB:

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

Con embrujamiento que puedo hacer:

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

Si los datos son bastante grandes (y tengo muchos de ellos) ¿hay una mejor manera de hacerlo?
¿Ayuda a calcular el (count m) de antemano?
¿Ayuda de antemano a defn el #(/ % (count m))?

Respuesta

4

Sin saber cómo utilizar el incanter, aquí se explica cómo se puede hacer esto "desde cero".

(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) 
+0

Gracias @amalloy funciona, pero no entiendo cómo '(aplicar mapa (fn ...' funcionaría, ¿no debería ser '(aplicar (mapa (fn ...'? – Ali

+1

@Ali No , estás aplicando la función 'map' a una secuencia de argumentos: una función anónima que construimos, y luego cada elemento de la secuencia' data'. 'map' está dispuesto a aceptar argumentos" adicionales ", pasándolos junto a la función. Por ejemplo, '(map + [1 2] [10 20])' ~ = '[(+ 1 10) (+ 2 20)]'. – amalloy

7

Aquí está una manera muy limpia y sencilla de hacerlo:

(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) 
+0

Me pregunté si (aplicar + coll) sería más eficiente then (reduce + coll). Ya respondí en http://stackoverflow.com/questions/3153396/clojure-reduce-vs-apply – NielsK

+0

Reducir es muy ligeramente más rápido (alrededor de 5-10% en pruebas informales que acabo de hacer) Pero en realidad se debe a las preferencias personales: tiendo a pensar en las operaciones de reducción más fácilmente que en el malabarismo de parámetros. – mikera

6

A partir de 2013, mi recomendación sería utilizar sólo core.matrix.stats para importar toda esta funcionalidad:

(mean [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]]) 
=> [3.0 6.0 5.0 5.0 6.0] 

core.matrix.stats se basa en la API core.matrix, por lo que también funcionará en otras implementaciones más optimizadas de vectores y matrices; esta es probablemente una mejor opción si está haciendo una gran cantidad de m pesados. procesamiento de atrix

Cuestiones relacionadas