Je veux écrire ce code en Pythonic. Mon vrai tableau est beaucoup plus grand que cet exemple.
(5 + 10 + 20 + 3 + 2)/5
print (np.mean (array, key = lambda x: x [1])) TypeError: mean () a obtenu un argument de mot clé inattendu 'key'
array = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]
sum = 0
for i in range(len(array)):
sum = sum + array[i][1]
average = sum / len(array)
print(average)
import numpy as np
print(np.mean(array,key=lambda x:x[1]))
Comment éviter cela? Je veux utiliser le deuxième exemple.
J'utilise Python 3.7
Si vous utilisez Python 3.4 ou supérieur, vous pouvez utiliser le statistics
module:
from statistics import mean
average = mean(value[1] for value in array)
Ou si vous utilisez une version de Python antérieure à 3.4:
average = sum(value[1] for value in array) / len(array)
Ces solutions utilisent toutes deux une fonctionnalité intéressante de Python appelée expression de générateur. La boucle
value[1] for value in array
crée une nouvelle séquence de manière rapide et efficace en mémoire. Voir PEP 289 - Expressions de générateur .
Si vous utilisez Python 2, et que vous additionnez des entiers, nous aurons une division entière, qui tronquera le résultat, par exemple:
>>> 25 / 4
6
>>> 25 / float(4)
6.25
Pour nous assurer que nous n'avons pas de division entière, nous pouvons définir la valeur de départ de sum
comme étant la valeur float
0.0
. Cependant, cela signifie également que nous devons rendre l'expression du générateur explicite avec des parenthèses, sinon c'est une erreur de syntaxe, et c'est moins joli, comme indiqué dans les commentaires:
average = sum((value[1] for value in array), 0.0) / len(array)
Il est probablement préférable d'utiliser fsum
à partir du (math
module qui renverra un float
:
from math import fsum
average = fsum(value[1] for value in array) / len(array)
Si vous souhaitez utiliser numpy
, convertissez-le en numpy.array
et sélectionnez l'axe souhaité à l'aide de l'indexation numpy
:
import numpy as np
array = np.array([('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)])
print(array[:,1].astype(float).mean())
# 8.0
La conversion en un type numérique est nécessaire car le tableau d'origine contient à la fois des chaînes et des nombres et est donc de type object
. Dans ce cas, vous pouvez utiliser float
ou int
, cela ne fait aucune différence.
Si vous êtes ouvert à des solutions plus proches du golf, vous pouvez transposer votre tableau avec Vanilla python, obtenir une liste des seuls chiffres et calculer la moyenne avec
sum(Zip(*array)[1])/len(array)
vous pouvez utiliser map
au lieu de la compréhension de liste
sum(map(lambda x:int(x[1]), array)) / len(array)
ou functools.reduce
(si vous utilisez Python2.X juste reduce
pas functools.reduce
)
import functools
functools.reduce(lambda acc, y: acc + y[1], array, 0) / len(array)
Vous pouvez simplement utiliser:
print(sum(tup[1] for tup in array) / len(array))
Ou pour Python 2:
print(sum(tup[1] for tup in array) / float(len(array)))
Ou un peu plus concis pour Python 2:
from math import fsum
print(fsum(tup[1] for tup in array) / len(array))
Avec Python pur:
from operator import itemgetter
acc = 0
count = 0
for value in map(itemgetter(1), array):
acc += value
count += 1
mean = acc / count
Une approche itérative peut être préférable si vos données ne peuvent pas tenir en mémoire en tant que list
(puisque vous avez dit qu'elles étaient volumineuses). Si c'est le cas, préférez une approche déclarative:
data = [sub[1] for sub in array]
mean = sum(data) / len(data)
Si vous êtes ouvert à l'utilisation de numpy
, je trouve ce nettoyeur:
a = np.array(array)
mean = a[:, 1].astype(int).mean()
Vous pouvez utiliser map
:
np.mean(list(map(lambda x: x[1], array)))
Le problème ici est que vous ne pouvez pas calculer directement la moyenne de la liste des tuples en tant que ndarray
car toutes les valeurs seront converties en str
.
Cependant, pour contourner ce problème, il faudrait définir un tableau structuré dans la liste des tuples, afin que vous puissiez associer un type de données différent à chaque élément des tuples.
Vous pouvez donc définir un tableau structuré à partir de la liste des tuples avec:
l = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]
a = np.array(l, dtype=([('str', '<U1'), ('num', '<i4')]))
Et puis prenez simplement le np.mean
du champ numérique, c'est-à-dire le deuxième élément des tuples:
np.mean(a['num'])
# 8.0
Il suffit de trouver la moyenne en utilisant la somme et le nombre d'éléments de la liste.
array = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]
avg = float(sum(value[1] for value in array)) / float(len(array))
print(avg)
#8.0