2017-08-01 1 views
1

J'ai une liste de dictionnaires. Je veux l'âge moyen des personnes dont l'âge est inférieur à 25.Valeur moyenne du sous-ensemble de valeurs dans une liste de dictionnaires

Je sais que mon diviseur est faux mais je ne suis pas sûr de savoir comment l'ajuster à l'intérieur de la compréhension.

Je reçois 81/8 = 10.125. Je devrais obtenir 81/5 = 16.2. Comment puis-je obtenir le diviseur pour correspondre au nombre d'éléments ajoutés?

people = [{'name': 'John', 'age': 47, 'hobbies': ['Python', 'cooking', 'reading']}, 
      {'name': 'Mary', 'age': 16, 'hobbies': ['horses', 'cooking', 'art']}, 
      {'name': 'Bob', 'age': 14, 'hobbies': ['Python', 'piano', 'cooking']}, 
      {'name': 'Sally', 'age': 11, 'hobbies': ['biking', 'cooking']}, 
      {'name': 'Mark', 'age': 54, 'hobbies': ['hiking', 'camping', 'Python', 'chess']}, 
      {'name': 'Alisa', 'age': 52, 'hobbies': ['camping', 'reading']}, 
      {'name': 'Megan', 'age': 21, 'hobbies': ['lizards', 'reading']}, 
      {'name': 'Amanda', 'age': 19, 'hobbies': ['turtles']}, 
      ] 


print(float(sum(d['age'] for d in people if d['age'] < 25))/len(people)) 

Répondre

1

au lieu de le faire en une seule compréhension de la liste, je le diviser en deux commandes comme ceci:

>>> under_25 = [x['age'] for x in people if x['age'] < 25] 
>>> avg_age = sum(under_25)/float(len(under_25)) 

Faire tout cela dans une compréhension de la liste auriez-vous besoin de le faire deux fois (une fois pour la somme au numérateur et une autre fois pour la longueur au dénominateur). Je pense que c'est plus lisible aussi.

Vous pouvez même essayer de le faire dans une boucle:

count = 0 
s = 0 
for person in people: 
    if person['age'] < 25: 
     s += person['age'] 
     count += 1 
avg_age = float(s)/count 
2

La solution la plus simple serait d'utiliser numpy avec une compréhension de la liste conditionnelle:

import numpy as np 

>>> np.mean([p['age'] for p in people if 'age' in p and p['age'] < 25]) 
16.199999999999999 

En utilisant une solution pure python, vous devrait garder une trace du total et le nombre que vous évaluez chaque élément de la collection. Cela réduit l'empreinte mémoire, car vous n'avez pas besoin de stocker toutes les valeurs correspondant à vos critères. Notez que j'ai utilisé un générateur dans l'énumération.

total_age = 0. 
for n, age in enumerate((p['age'] for p in people if 'age' in p and p['age'] < 25), start=1): 
    total_age += age 
>>> print(total_age/n) 
16.2 
1

Python dispose d'un module statistics qui contient une fonction mean:

>>> from statistics import mean 
>>> mean(d['age'] for d in people if d['age'] < 25) 
16.2 

Ou si vous avez pandas vous pouvez le faire avec l'indexation booléenne:

>>> import pandas as pd 

>>> df = pd.DataFrame(people, columns=['name', 'age', 'hobbies']) 
>>> df[df['age'] < 25]['age'].mean() 
16.2 

La seule df[df['age'] < 25] contient les les lignes qui ont un âge inférieur à 25 et le ['age'].mean() calcule ensuite la moyenne colonne "age".