Numpy: разделите каждую строку на векторный элемент
Предположим, что у меня есть массив numpy:
data = np.array([[1,1,1],[2,2,2],[3,3,3]])
и у меня есть соответствующий "вектор:"
vector = np.array([1,2,3])
Как я могу работать с data
вдоль каждой строки, чтобы вычесть или разделить так, чтобы результат:
sub_result = [[0,0,0], [0,0,0], [0,0,0]]
div_result = [[1,1,1], [1,1,1], [1,1,1]]
Короче говоря: как выполнить операцию над каждой строкой двумерного массива с 1D массивом скаляров, который соответствует каждой строке?
Ответы
Ответ 1
Здесь вы идете. Вам просто нужно использовать None
(или альтернативно np.newaxis
) в сочетании с трансляцией:
In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
Ответ 2
Как уже упоминалось, нарезка с помощью None
или с np.newaxes
- отличный способ сделать это.
Другой альтернативой является использование транспонирования и трансляции, как в
(data.T - vector).T
и
(data.T / vector).T
Для массивов с более высокой размерностью вы можете использовать метод swapaxes
для массивов NumPy или функцию NumPy rollaxis
.
Существует действительно много способов сделать это.
Для более полного объяснения вещания см.
http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
Ответ 3
В решении JoshAdel для добавления измерения используется np.newaxis. Альтернативой является использование reshape() для выравнивания размеров при подготовке к трансляции.
data = np.array([[1,1,1],[2,2,2],[3,3,3]])
vector = np.array([1,2,3])
data
# array([[1, 1, 1],
# [2, 2, 2],
# [3, 3, 3]])
vector
# array([1, 2, 3])
data.shape
# (3, 3)
vector.shape
# (3,)
data / vector.reshape((3,1))
# array([[1, 1, 1],
# [1, 1, 1],
# [1, 1, 1]])
Выполнение функции reshape() позволяет объединить размеры для трансляции:
data: 3 x 3
vector: 3
vector reshaped: 3 x 1
Обратите внимание, что data/vector
в порядке, но он не дает вам ответ, который вы хотите. Он разбивает каждый столбец array
(вместо каждой строки) на каждый соответствующий элемент vector
. Это то, что вы получили бы, если бы я явно переформатировал vector
как 1x3
вместо 3x1
.
data / vector
# array([[1, 0, 0],
# [2, 1, 0],
# [3, 1, 1]])
data / vector.reshape((1,3))
# array([[1, 0, 0],
# [2, 1, 0],
# [3, 1, 1]])
Ответ 4
Pythonic способ сделать это...
np.divide(data,vector)
Это позволяет изменить форму, а также результаты в формате с плавающей запятой. В других ответах результаты представлены в округленном целочисленном формате.
# ПРИМЕЧАНИЕ: количество столбцов в данных и векторе не должно совпадать
Ответ 5
Добавляя к ответу stackoverflowuser2010, в общем случае вы можете просто использовать
data = np.array([[1,1,1],[2,2,2],[3,3,3]])
vector = np.array([1,2,3])
data / vector.reshape(-1,1)
Это превратит ваш вектор в column matrix/vector
. Позволяет вам выполнять поэлементные операции, как вы хотите. По крайней мере, для меня это наиболее интуитивный способ, и (в большинстве случаев) numpy будет использовать только ту же внутреннюю память для эффективного преобразования.