Numpy: Розділіть кожен рядок векторним елементом


119

Припустимо, у мене є масивний ряд:

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

Довге коротке оповідання: Як мені виконати операцію над кожним рядом 2D масиву з 1D масивом скалярів, який відповідає кожному рядку?

Відповіді:


181

Ось ви йдете. Вам просто потрібно використовувати 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]])



@ user108569, використовуючи останню версію numpy (1.18.1), Noneвсе ще працює еквівалентно np.newaxis. Я не впевнений, яка ваша установка чи точна проблема, яку ви маєте, але відповідь все-таки справедлива.
JoshAdel

11

Як уже згадувалося, нарізання з Noneабо з np.newaxes- це відмінний спосіб зробити це. Інша альтернатива - використовувати транспозицію та мовлення, як в

(data.T - vector).T

і

(data.T / vector).T

Для масивів більш високих розмірів ви можете скористатися swapaxesметодом масивів NumPy або rollaxisфункцією NumPy . Насправді існує маса способів зробити це.

Більш повне пояснення мовлення див. На веб-сторінці http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html


4

Рішення JoshAdel використовує np.newaxis для додавання виміру. Альтернативою є використання переформатування () для вирівнювання розмірів під час підготовки до мовлення .

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

Виконання переформатування () дозволяє розмірам вирівнюватися для мовлення:

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

2

Пітонічний спосіб це зробити ...

np.divide(data.T,vector).T

Це вимагає переформування, а також результати у форматі з плаваючою комою. В інших відповідях результати є у закругленому цілому форматі.

# ПРИМІТКА: Жоден стовпець і в даних, і в векторному не повинен збігатися


Примітка. Це не робить того, чого вимагає ОП. Кінцевий результат - масив ([[1., 0.5, 0.33333333], [2., 1., 0.66666667], [3., 1.5, 1.]]). Це може бути "пітонічно", але це неправильно.
Марк Креймер

1
@MarkCramer Дякую Я виправив свою відповідь, щоб забезпечити правильний результат.
шантану патхак

1

Додавши до відповіді stackoverflowuser2010, в загальному випадку ви можете просто використовувати

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

vector = np.array([1,2,3])

data / vector.reshape(-1,1)

Це перетворить ваш вектор в a column matrix/vector. Дозволяє робити поетапні операції за своїм бажанням. Принаймні, для мене, це найбільш інтуїтивно зрозумілий спосіб, і оскільки (в більшості випадків) numpy просто використовуватиме вигляд тієї самої внутрішньої пам'яті для переробки, це також ефективно.


Це має бути прийнятою відповіддю. Створення вектора стовпців за .reshape(-1,1) допомогою найбільш інтуїтивного способу використання мовлення.
Пол Рудьо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.