Numpy широковещательный массив - PullRequest
2 голосов
/ 06 сентября 2010

У меня есть следующий массив в NumPy:

A = array([1, 2, 3])

Как получить следующие матрицы (без явного цикла)?

B = [ 1 1 1
      2 2 2
      3 3 3 ]

C = [ 1 2 3
      1 2 3
      1 2 3 ]

Спасибо!

Ответы [ 2 ]

7 голосов
/ 06 сентября 2010

Edit2: ОП спрашивает в комментариях, как вычислить

n(i, j) = l(i, i) + l(j, j) - 2 * l(i, j)

Я могу придумать два пути. Мне нравится этот способ, потому что он легко обобщается:

import numpy as np

l=np.arange(9).reshape(3,3)
print(l)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

Идея состоит в том, чтобы использовать np.ogrid. Это определяет список из двух массивов NumPy, один из формы (3,1) и один из формы (1,3):

grid=np.ogrid[0:3,0:3]
print(grid)
# [array([[0],
#        [1],
#        [2]]), array([[0, 1, 2]])]

grid[0] может использоваться в качестве прокси для индекса i, и grid[1] может использоваться в качестве прокси для индекса j.

Поэтому везде в выражении l(i, i) + l(j, j) - 2 * l(i, j) вы просто заменяете i -> grid[0] и j -> grid[1], а остальное вещание позаботится обо всем остальном:

n=l[grid[0],grid[0]] + l[grid[1],grid[1]] + 2*l
print(n)
# [[ 0  6 12]
#  [10 16 22]
#  [20 26 32]]

Однако, в данном конкретном случае, поскольку l(i,i) и l(j,j) являются только диагональными элементами l, вы можете сделать это вместо этого:

d=np.diag(l)
print(d)
# [0 4 8]

d[np.newaxis,:] накачивает форму от d до (1,3), и d[:,np.newaxis] накачивает форму от d до (3,1).

Numpy широковещательная рассылка d[np.newaxis,:] и d[:,np.newaxis], чтобы сформировать (3,3), копируя значения соответствующим образом.

n=d[np.newaxis,:] + d[:,np.newaxis] + 2*l
print(n)
# [[ 0  6 12]
#  [10 16 22]
#  [20 26 32]]

Edit1: Обычно вам не нужно формировать B или C. Цель вещания Numpy - позволить вам использовать A вместо B или C. Если вы покажете нам, как вы планируете использовать B или C, мы можем показать вам, как сделать то же самое с A и бесшумной трансляцией.


(Оригинальный ответ):

In [11]: B=A.repeat(3).reshape(3,3)

In [12]: B
Out[12]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

In [13]: C=B.T

In [14]: C
Out[14]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

или

In [25]: C=np.tile(A,(3,1))

In [26]: C
Out[26]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

In [27]: B=C.T

In [28]: B
Out[28]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

Из отдела грязных трюков:

In [57]: np.lib.stride_tricks.as_strided(A,shape=(3,3),strides=(4,0))
Out[57]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

In [58]: np.lib.stride_tricks.as_strided(A,shape=(3,3),strides=(0,4))
Out[58]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

Но обратите внимание, что это представления из A, а не копии (как и решения выше). Изменение B, изменение A:

In [59]: B=np.lib.stride_tricks.as_strided(A,shape=(3,3),strides=(4,0))

In [60]: B[0,0]=100

In [61]: A
Out[61]: array([100,   2,   3])

3 голосов
/ 22 января 2013

Очень старая тема, но на случай, если кому-то все равно ...

C,B = np.meshgrid(A,A)
...