Assume we have the following matrix:
M=[[ 19. 1. 8.]
[ 3. 6. 900.]
[ 4. 11. 44.]
[ 2. 50. 12.]]
and we have the following vector:
V=[0,3,2]
we want to build the following matrix:
P=[[ 19. 50. 44.]
[ 19. 50. 44.]
[ 19. 50. 44.]
[ 19. 50. 44.]]
Basically, we want to use each element of V as index for M which is M[V[0],0] is 19, M[V[1],1] is 50, and M[V[2],2] is 44. What is the efficient to this using numpy and without for-loop?
I can do it as follow:
temp=M[V[np.arange(v.shape[0])],np.arange(v.shape[0])]
P=np.tile(temp,(M.shape[0],1))
but is there a better way?
M[V,[0,1,2]][None,:].repeat(4,0)
M[V,[0,1,2]]
produces the 1d array: array([19, 50, 44])
. The rest expands it to 4 rows.
A alternate way to expand it:
np.tile(M[V,[0,1,2]],[4,1])
With tile
, each row is a copy of the original row. A different way of 'expanding' the row uses strides:
M2=np.broadcast_arrays(M[V,[0,1,2]],np.zeros((4,1)))[0]
In this case each row shares the same data. For large arrays it saves on space. But if you do M2[1,1]=30
, you will end up changing the whole column. It's a variation on broadcasting: M[V, [0,1,2]][None,:]
. It comes down to, 'why do you need 4 identical rows?'.
One more way, taking advantage of how Python 'multiplies' a list:
M[np.array(V*4).reshape(4,-1), [0,1,2]]
On some quick tests, this is actually the fastest, but I don't know how it scales.
use numpy.diagonal
first, then numpy.repeat
:
In [168]: dia = tg[v].diagonal()[None,:]
In [169]: dia.repeat(4, axis=0)
Out[169]:
array([[19, 50, 44],
[19, 50, 44],
[19, 50, 44],
[19, 50, 44]])
or numpy.tile
:
In [172]: np.tile(dia, (4, 1))
Out[172]:
array([[19, 50, 44],
[19, 50, 44],
[19, 50, 44],
[19, 50, 44]])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.