Сложение всех пар столбцов двух матриц

У меня есть две матрицы A и B с одинаковым количеством столбцов, но обычно с неравным количеством строк. Я хочу сложить все пары столбцов из матриц A и B. Наивная реализация с циклом for такова:

import numpy as np
ncol = 3
nrow_A = 5
nrow_B = 10
A = np.ones((nrow_A,ncol))
B = np.zeros((nrow_B,ncol))

C = np.empty((nrow_A*nrow_B,ncol))
k = 0
for i in range(nrow_A):
    for j in range(nrow_B):
        C[k,:] = A[i,:]+B[j,:] 
        k += 1

который в этом примере возвращает матрицу 50 * 3, заполненную единицами. Такое ощущение, что это должно быть возможно с помощью одной строки кода. Как я могу этого добиться?


person Forzaa    schedule 18.11.2014    source источник


Ответы (2)


Если вы немного измените форму A, вы можете сложить две матрицы вместе и соединить записи на первой оси результирующего массива:

>>> np.concatenate(A[:,np.newaxis,:] + B)
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       ...

Чуть более быстрая альтернатива concatenate — использовать reshape:

(A[:,np.newaxis,:] + B).reshape(-1, 3)
person Alex Riley    schedule 18.11.2014
comment
Спасибо. Разве конкатенация не довольно дорогая операция? - person Forzaa; 18.11.2014
comment
@Forzaa - это правда, может быть; вместо этого вы можете использовать reshape (я добавил его в ответ) - person Alex Riley; 18.11.2014
comment
Большой! Действительно удобное использование функций numpy. На данный момент я еще недостаточно опытен, чтобы увидеть все возможности, поэтому очень приятно видеть эти примеры. - person Forzaa; 18.11.2014

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

(A[:, np.newaxis, :] + B[np.newaxis, :, :]).reshape(nrow_A * nrow_B, ncol)

Пример

import numpy as np
ncol = 3
nrow_A = 5
nrow_B = 10
A = np.random.random_sample((nrow_A,ncol))
B = np.random.random_sample((nrow_B,ncol))

C = np.empty((nrow_A*nrow_B,ncol))
k = 0
for i in range(nrow_A):
    for j in range(nrow_B):
        C[k,:] = A[i,:]+B[j,:] 
        k += 1

D = (A[:, np.newaxis, :] + B[np.newaxis, :, :]).reshape(nrow_A * nrow_B, ncol)

print(np.allclose(C, D))
person YXD    schedule 18.11.2014
comment
Тай. Вы дали почти тот же ответ, что и Ajcr, но, поскольку его версия также включает альтернативу, я принял ее. - person Forzaa; 18.11.2014