Есть ли какой-нибудь pythonic способ найти среднее значение определенных элементов кортежа в массиве?

Я хочу написать этот код как pythonic. Мой реальный массив намного больше, чем этот пример.

(5 + 10 + 20 + 3 + 2)/5

print (np.mean(array, key = lambda x: x [1])) TypeError: mean() получил неожиданный аргумент ключевого слова '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]))

Как можно избежать этого? Я хочу использовать второй пример.

Я использую Python 3.7

Ответы

Ответ 1

Если вы используете Python 3.4 или выше, вы можете использовать модуль statistics:

from statistics import mean

average = mean(value[1] for value in array)

Или, если вы используете версию Python старше 3.4:

average = sum(value[1] for value in array) / len(array)

Оба эти решения используют приятную особенность Python, называемую выражением генератора. Петля

value[1] for value in array

своевременно и эффективно использует новую последовательность. См. PEP 289 - Выражения генератора.

Если вы используете Python 2 и суммируете целые числа, у нас будет целочисленное деление, которое будет усекать результат, например:

>>> 25 / 4
6

>>> 25 / float(4)
6.25

Чтобы гарантировать, что у нас нет целочисленного деления, мы можем установить начальное значение sum равным значению с float 0.0. Однако это также означает, что мы должны сделать выражение генератора явным образом с круглыми скобками, в противном случае это синтаксическая ошибка, и она менее привлекательна, как отмечено в комментариях:

average = sum((value[1] for value in array), 0.0) / len(array)

Вероятно, лучше использовать fsum из math модуля, который будет возвращать float:

from math import fsum

average = fsum(value[1] for value in array) / len(array)

Ответ 2

Если вы хотите использовать numpy, numpy.array его к numpy.array и выберите numpy.array ось, используя индексирование 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

Приведение к числовому типу необходимо, поскольку исходный массив содержит как строки, так и числа и, следовательно, имеет тип object. В этом случае вы можете использовать float или int, это не имеет значения.

Ответ 3

Вы можете просто использовать:

print(sum(tup[1] for tup in array) / len(array))

Или для Python 2:

print(sum(tup[1] for tup in array) / float(len(array)))

Или немного более кратко для Python 2:

from math import fsum

print(fsum(tup[1] for tup in array) / len(array))

Ответ 4

С чистого Python:

from operator import itemgetter

acc = 0
count = 0

for value in map(itemgetter(1), array):
    acc += value
    count += 1

mean = acc / count

Итеративный подход может быть предпочтительным, если ваши данные не могут поместиться в памяти в виде list (так как вы сказали, что он большой). Если это возможно, предпочтите декларативный подход:

data = [sub[1] for sub in array]
mean = sum(data) / len(data)

Если вы открыты для использования numpy, я нахожу этот очиститель:

a = np.array(array)

mean = a[:, 1].astype(int).mean()

Ответ 5

Если вы открыты для более похожих на гольф решений, вы можете транспонировать массив с помощью vanilla python, получить список только чисел и рассчитать среднее с помощью

sum(zip(*array)[1])/len(array)

Ответ 6

Вы можете использовать map вместо понимания списка

sum(map(lambda x:int(x[1]), array)) / len(array)

или functools.reduce (если вы используете Python2.X, просто reduce не functools.reduce)

import functools
functools.reduce(lambda acc, y: acc + y[1], array, 0) / len(array)

Ответ 7

Вы можете использовать map:

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

Ответ 8

Просто найдите среднее значение, используя сумму и количество элементов списка.

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

Ответ 9

Проблема здесь в том, что вы не можете напрямую вычислить среднее значение списка кортежей как ndarray потому что все значения будут приведены к str.

Однако можно обойти это путем определения структурированного массива из списка кортежей, чтобы можно было связать разные типы данных с каждым элементом в кортежах.

Таким образом, вы можете определить структурированный массив из списка кортежей с помощью:

l = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]
a = np.array(l, dtype=([('str', '<U1'), ('num', '<i4')]))

А затем просто возьмите np.mean числового поля, то есть второй элемент в кортежах:

np.mean(a['num'])
# 8.0