Есть ли какой-нибудь 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