Среднее значение подмножества значений в списке словарей

У меня есть список словарей. Я хочу средний возраст людей, чей возраст меньше 25 лет.

Я знаю, что мой делитель неправильный, но я не уверен, как отрегулировать его внутри понимания.

Я получаю 81/8 = 10,125. Я должен получить 81/5 = 16,2. Как получить делитель в соответствии с количеством добавляемых элементов?

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

3 ответа

Решение

Вместо того, чтобы делать все это в одном понимании списка, я бы разбил его на две команды следующим образом:

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

Выполнение всего этого в одном понимании списка потребовало бы, чтобы вы делали это дважды (один раз для суммы в числителе и другой раз для длины в знаменателе). Я думаю, что это также более читабельно.

Вы даже можете попробовать сделать это в цикле for:

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

Самым простым решением было бы использовать numpy с условным списком понимания:

import numpy as np

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

Используя чистое Python-решение, вы должны отслеживать общее количество и количество при оценке каждого элемента в коллекции. Это уменьшает объем памяти, поскольку вам не нужно хранить все значения, соответствующие вашим критериям. Обратите внимание, что я использовал генератор в перечислении.

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

Python имеет statistics модуль, который содержит mean функция:

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

Или если у вас есть pandas Вы можете сделать это с помощью логического индексирования:

>>> import pandas as pd

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

df[df['age'] < 25] содержит только те строки, которые имеют возраст до 25 лет и ['age'].mean() затем вычисляет среднее значение столбца "возраст".

Другие вопросы по тегам