web-dev-qa-db-fra.com

Existe-t-il un moyen Pythonic de trouver la moyenne des éléments Tuple spécifiques dans le tableau?

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

23
Şevval Kahraman

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 float0.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)
26
Peter Wood

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.

3
Graipher

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)
3
Nick Amin

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)
2
minji

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))
2
ruohola

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()
2
gmds

Vous pouvez utiliser map:

np.mean(list(map(lambda x: x[1], array)))

0
pdpino

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
0
yatu

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
0
Devesh Kumar Singh