Convertir el promedio de los valores de la lista de Python en otra lista

Tengo listas como esta.

list = [["Joe", 5, 7], ["Joe", 6, 9], ["Mike", 1,4], ["Joe", 7,4], ["Mike", 5,7]] 

¿Cómo puedo convertir esta lista a una lista como esta:

 list2 = [["Joe", 6.00, 6.66], ["Mike", 3.00, 5.50]] 

list2 [0] [1] y list2 [1] [1] son ​​los valores promedio de la primera lista con personas específicas (6.00 proviene de (list[0][1]+list[1][1]+list[3][1])/3

Debería usar la iteración de esta manera:

 for i in range(len(list)): ... 

¿o algo así? Porque estoy importando la lista de SQLite y la lista siempre está cambiando.

Como dice que está importando la lista desde sqlite, puede interesarle usar un paquete de procesamiento de datos existente en lugar de rodar su propia función por función. Por ejemplo, en pandas , podría cargar los datos en un DataFrame :

 >>> df = pd.DataFrame(yourlist) >>> df 0 1 2 0 Joe 5 7 1 Joe 6 9 2 Mike 1 4 3 Joe 7 4 4 Mike 5 7 [5 rows x 3 columns] >>> df.groupby(0).mean() 1 2 0 Joe 6 6.666667 Mike 3 5.500000 [2 rows x 2 columns] 

Ahora, usar pandas sería un exceso excesivo para el problema de forma aislada, pero si está extrayendo datos de una base de datos, probablemente querrá hacer varias cosas con los datos.

Esto funciona para cualquier número de valores que esté sumndo (en su caso dos):

Python 3

 from collections import defaultdict rows = [["Joe", 5, 7], ["Joe", 6, 9], ["Mike", 1,4], ["Joe", 7,4], ["Mike", 5,7]] d = defaultdict(list) for k, *v in rows: d[k].append(v) averages = [[k] + [sum(x) / len(v) for x in zip(*v)] for k, v in d.items()] print(averages) 

Python 2

Reemplace los items() con iteritems() , agregue una iteritems() float alrededor de la sum(x) , use print con un espacio, no parens, y cambie el bucle for a

 for row in rows: d[row[0]].append(row[1:]) 

(Python 3 es seguro agradable).


Explicación

defaultdict y for loop crean un mapa desde el nombre a una lista del valor.

 {'Mike': [[1, 4], [5, 7]], 'Joe': [[5, 7], [6, 9], [7, 4]]} 

k, v in d.items() itera sobre cada nombre y lista de listas.

zip(*v) toma algo como [[5, 7], [6, 9], [7, 4]] y lo convierte en [[5, 6, 7], [7, 9, 4]] . Luego summos estos y dividimos por el número de listas originales.

Agregamos [k] y esta lista de promedios para obtener una lista como ['Joe', 6.0, 6.67] .

Por cierto, si esto proviene de una base de datos, ¿has considerado hacer la agregación allí?

Algo como esto:

 >>> from collections import OrderedDict >>> lis = [["Joe", 5, 7], ["Joe", 6, 9], ["Mike", 1,4], ["Joe", 7,4], ["Mike", 5,7]] >>> d = OrderedDict() >>> for item in lis: ... d.setdefault(item[0], []).append(item[1:]) 

Ahora d contiene:

 >>> d OrderedDict([('Joe', [[5, 7], [6, 9], [7, 4]]), ('Mike', [[1, 4], [5, 7]])]) 

El ordenado de las claves únicas que se han visto se conserva aquí ya que usamos un OrderedDict aquí.

Ahora podemos iterar sobre este diccionario y obtener el promedio de columnas para cada clave. zip con * nos permite obtener una transposición de una lista muy fácilmente:

 >>> zip(*[[5, 7], [6, 9], [7, 4]]) [(5, 6, 7), (7, 9, 4)] >>> 

Comprensión final de la lista:

 >>> [[k] + [sum(x)/float(len(x)) for x in zip(*v)] for k, v in d.items()] [['Joe', 6.0, 6.666666666666667], ['Mike', 3.0, 5.5]] 

Puedes eliminar la llamada float en Python3. Y si el orden de los nombres ‘Joe’, ‘Mike’ no importa en la lista de salida, simplemente puede usar un dict normal con dict.setdefault o usar collections.defaultdict .

Usando itertools.groupby :

 >>> from itertools import groupby >>> data = [["Joe", 5, 7], ["Joe", 6, 9], ["Mike", 1, 4], ["Joe", 7, 4], ["Mike", 5, 7]] >>> data.sort() >>> result = [] >>> for _, groups in groupby(d, lambda x: x[0]): it = iter(zip(*groups)) row = [next(it)[0]] for values in it: row.append(sum(values) / len(values)) result.append(row) >>> result [['Joe', 6.0, 6.666666666666667], ['Mike', 3.0, 5.5]] 

Una solución alternativa. Es un poco complicado pero de una sola línea sin importaciones.

 map(lambda x : [x[0],float(x[1])/x[3],float(x[2])/x[3]],reduce(lambda x,y : x[0:(len(x)-1)] + [[x[-1][0],x[-1][1]+y[1],x[-1][2]+y[2],x[-1][3]+1]] if ((y[0] == x[-1][0]) if (len(x)>0) else False) else x + [[y[0],y[1],y[2],1]] ,arr,[]))