2012-06-06 12 views
18

tengo una lista de listas: algo como:lista de promedios de las listas de pitón

data = [[240, 240, 239], 
     [250, 249, 237], 
     [242, 239, 237], 
     [240, 234, 233]] 

Y quiero promediar esto como

[average_column_1, average_column_2, average_column_3] 

Mi pieza de código es como no muy elegante . Es la manera ingenua de ir a través de la lista, manteniendo la suma en un contenedor separado y luego dividiéndolo por el número de elementos.

Creo que hay una manera pitónica de hacer esto. ¿Alguna sugerencia? Gracias

Respuesta

36

Python puro:

from __future__ import division 
def mean(a): 
    return sum(a)/len(a) 
a = [[240, 240, 239], 
     [250, 249, 237], 
     [242, 239, 237], 
     [240, 234, 233]] 
print map(mean, zip(*a)) 

impresión

[243.0, 240.5, 236.5] 

NumPy:

a = numpy.array([[240, 240, 239], 
       [250, 249, 237], 
       [242, 239, 237], 
       [240, 234, 233]]) 
print numpy.mean(a, axis=0) 

Python 3:

from statistics import mean 
print(*map(mean, zip(*a)) 
+0

Preferible con 'from itertools import imap, izip' – schlamar

+3

@ ms4py:' from future_builtins import map, zip' si decides ir por esta ruta – georg

+0

@ thg435 Esto es nuevo, es bueno saber :) – schlamar

13

Use zip(), así:

averages = [sum(col)/float(len(col)) for col in zip(*data)] 

zip() toma varios argumentos iterables, y devuelve rebanadas de esos iterables (como tuplas), hasta que uno de los iterables no puede devolver nada más. En efecto, realiza una operación de transposición, similar a las matrices.

>>> data = [[240, 240, 239], 
...   [250, 249, 237], 
...   [242, 239, 237], 
...   [240, 234, 233]] 

>>> [list(col) for col in zip(*data)] 
[[240, 250, 242, 240], 
[240, 249, 239, 234], 
[239, 237, 237, 233]] 

Mediante la realización de sum() en cada una de esas porciones, se obtiene de manera efectiva la suma por columnas. Simplemente divida por la longitud de la columna para obtener la media.

Punto lateral: en Python 2.x, la división en enteros limita el decimal de forma predeterminada, por lo que se llama a float() para "promover" el resultado a un tipo de coma flotante.

+0

No te olvides de dividir por la longitud;) – mgilson

+5

Vale la pena agregar una explicación: 'zip' es una función que toma múltiples secuencias y devuelve tuplas en una base" columna por columna ". Entonces regresa (x [0] [0], x [1] [0], x [2] [0]) luego (x [1] [0], x [1] [1], x [1] [2]) y así sucesivamente. Sin embargo, dejará de recuperarse tan pronto como se quede sin elementos para una línea determinada. Es más fácil diagramar en el código, cuidado de mostrar cómo funciona? – Crisfole

18
data = [[240, 240, 239], 
     [250, 249, 237], 
     [242, 239, 237], 
     [240, 234, 233]] 
avg = [float(sum(col))/len(col) for col in zip(*data)] 
# [243.0, 240.5, 236.5] 

Esto funciona porque zip(*data) le dará una lista con las columnas agrupadas, la llamada float() sólo es necesario en Python 2.x, que utiliza la división entera a menos que se utiliza from __future__ import division.

+0

Creo que esta respuesta es la mejor. También fue el primero. –

+1

@BlaXpirit: Se pone demasiado énfasis en la velocidad en SO, lo importante debería ser la calidad. También tenga en cuenta que esta respuesta llegó en tercer lugar (o cuarto, si contamos la respuesta eliminada). –

1
import numpy as np 

data = [[240, 240, 239], 
     [250, 249, 237], 
     [242, 239, 237], 
     [240, 234, 233]] 

np.mean(data, axis=0) 
# array([ 243. , 240.5, 236.5]) 

Parece que funciona.

Cuestiones relacionadas