У меня есть два массива чисел, и я хочу вычислить средневзвешенное значение по элементам между этими массивами и сохранить его в новом массиве.
Решение, которое я использую на данный момент:
array_1 = [0,1,2,3,4]
array_2 = [2,3,4,5,6]
weight_1 = 0.5
weight_2 = 0.5
array_3 = np.zeros(array_1.shape)
for i in range(0, len(array_1)) :
array_3[i] = np.average(a=[array_1[i], array_2[i]], weights=[weight_1, weight_2])
print(array_3)
>> [1,2,3,4,5]
Проблема в том, что это не очень эффективно. Как я могу сделать это более эффективно?
Вы можете молния обоих итераторов и умножать каждый элемент на соответствующий вес
array_1 = [0,1,2,3,4]
array_2 = [2,3,4,5,6]
weight_1 = 0.5
weight_2 = 0.5
#Zip both iterators and multiply weight with corresponding item
result = [ item1 * weight_1 + item2 * weight_2 for item1, item2 in zip(array_1, array_2)]
print(result)
Результат будет
[1.0, 2.0, 3.0, 4.0, 5.0]
Учитывая, что вы используете NumPy, вы можете легко векторизовать это, выполнив:
array_1 = np.array([0,1,2,3,4])
array_2 = np.array([2,3,4,5,6])
weight_1 = 0.5
weight_2 = 0.5
array_1*weight_1 + array_2*weight_2
# array([1., 2., 3., 4., 5.])
Можно ли это обобщить для нескольких массивов и весов?
Для более обобщенного ответа лучше всего использовать np.average
, который принимает array_like
как для массивов, так и для применения weights
к каждому из них:
np.average([array_1, array_2], weights=[weight_1, weight_2], axis=0)
# array([1., 2., 3., 4., 5.])
Ну, ОП сказал более эффективное решение. Итак, мы ищем векторизованный здесь @DeveshKumarSingh
Таким образом, векторизация numpy более эффективна, чем архивирование и список компов @yatu?
Да, как правило, так и есть, поскольку вы опускаете все циклы до уровня c
@DeveshKumarSingh
@DeveshKumarSingh: Проверьте мой ответ на точность синхронизации. Ваш метод действительно выигрывает здесь но Я уверен, что для больших массивов векторизованное решение возьмет верх
Конечно. Если OP хочет производительности, предполагается, что мы говорим о больших массивах. И способ проверить производительность здесь, и всегда с numpy, — с гораздо большими выборками.
@yatu: я с тобой согласен
Просто используйте векторизованные операции NumPy. Для этого сначала преобразуйте свои списки в массивы, а затем просто умножьте каждый массив на соответствующий вес и возьмите сумму
import numpy as np
array_1 = np.array([0,1,2,3,4])
array_2 = np.array([2,3,4,5,6])
weight_1 = 0.5
weight_2 = 0.5
array_3 = weight_1*array_1 + weight_2*array_2
# array([1., 2., 3., 4., 5.])
Прямое решение NumPy с использованием np.average
будет следующим, где axis=0
означает получение среднего значения по строке (с использованием обоих столбцов). np.vstack()
просто складывает два массива вертикально.
np.average(np.vstack((array_1, array_2)), axis=0, weights=[weight_1, weight_2])
Как указал @yatu, вы также можете передать список своих массивов и указать ось
np.average([array_1, array_2], axis=0, weights=[weight_1, weight_2])
Сравнение времени, вдохновленное комментариями к ответу @yatu: Как вы можете видеть, понимание списка и zip здесь немного быстрее, но тогда эта производительность для небольших массивов. Я уверен, что для больших массивов векторизованное решение возьмет верх
Метод Девеша
%timeit result = [ item1 * weight_1 + item2 * weight_2 for item1, item2 in zip(array_1, array_2)]
# 25.5 µs ± 3.75 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit np.average([array_1, array_2], axis=0, weights=[weight_1, weight_2])
# 42.9 µs ± 2.94 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit np.average(np.vstack((array_1, array_2)), axis=0, weights=[weight_1, weight_2])
# 44.8 µs ± 4.98 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Разве уравнение для средневзвешенного значения не должно быть:
(array_1*weight_1 + array_2*weight_2)/(weight_1 + weighted_2)
Это не похоже на ответ, но может быть уместным комментарием. Пожалуйста, напишите как комментарий к вопросу. Необязательно ссылка на изображение теории.
Я хотел, но я не мог опубликовать это как комментарий, так как моя репутация ниже 50, и я мог опубликовать это только как ответ.
Нет никого для
zip
решения :)