IT story

"복제"행 또는 열 벡터

hot-time 2020. 7. 3. 18:14
반응형

"복제"행 또는 열 벡터


때때로 행 또는 열 벡터를 행렬에 "복제"하는 것이 유용합니다. 복제함으로써 나는 다음과 같은 행 벡터를 변환하는 것을 의미합니다.

[1,2,3]

행렬로

[[1,2,3]
 [1,2,3]
 [1,2,3]
]

또는 다음과 같은 열 벡터

[1
 2
 3
]

으로

[[1,1,1]
 [2,2,2]
 [3,3,3]
]

matlab 또는 옥타브에서 이것은 매우 쉽게 수행됩니다.

 x = [1,2,3]
 a = ones(3,1) * x
 a =

    1   2   3
    1   2   3
    1   2   3

 b = (x') * ones(1,3)
 b =

    1   1   1
    2   2   2
    3   3   3

나는 이것을 numpy로 반복하고 싶지만 실패했습니다.

In [14]: x = array([1,2,3])
In [14]: ones((3,1)) * x
Out[14]:
array([[ 1.,  2.,  3.],
       [ 1.,  2.,  3.],
       [ 1.,  2.,  3.]])
# so far so good
In [16]: x.transpose() * ones((1,3))
Out[16]: array([[ 1.,  2.,  3.]])
# DAMN
# I end up with 
In [17]: (ones((3,1)) * x).transpose()
Out[17]:
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.],
       [ 3.,  3.,  3.]])

첫 번째 방법 (In [16])이 효과가없는 이유는 무엇입니까? 파이썬 에서이 작업을보다 우아한 방법으로 달성 할 수있는 방법이 있습니까?


우아하고 파이썬적인 방법은 다음과 같습니다.

>>> array([[1,2,3],]*3)
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

>>> array([[1,2,3],]*3).transpose()
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

문제 [16]는 조옮김이 배열에 영향을 미치지 않는다는 것 같습니다. 아마도 대신 행렬을 원할 것입니다.

>>> x = array([1,2,3])
>>> x
array([1, 2, 3])
>>> x.transpose()
array([1, 2, 3])
>>> matrix([1,2,3])
matrix([[1, 2, 3]])
>>> matrix([1,2,3]).transpose()
matrix([[1],
        [2],
        [3]])

사용 numpy.tile:

>>> tile(array([1,2,3]), (3, 1))
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

또는 반복되는 열의 경우 :

>>> tile(array([[1,2,3]]).transpose(), (1, 3))
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

First note that with numpy's broadcasting operations it's usually not necessary to duplicate rows and columns. See this and this for descriptions.

But to do this, repeat and newaxis are probably the best way

In [12]: x = array([1,2,3])

In [13]: repeat(x[:,newaxis], 3, 1)
Out[13]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

In [14]: repeat(x[newaxis,:], 3, 0)
Out[14]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

This example is for a row vector, but applying this to a column vector is hopefully obvious. repeat seems to spell this well, but you can also do it via multiplication as in your example

In [15]: x = array([[1, 2, 3]])  # note the double brackets

In [16]: (ones((3,1))*x).transpose()
Out[16]: 
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.],
       [ 3.,  3.,  3.]])

I think using the broadcast in numpy is the best, and faster

I did a compare as following

import numpy as np
b = np.random.randn(1000)
In [105]: %timeit c = np.tile(b[:, newaxis], (1,100))
1000 loops, best of 3: 354 µs per loop

In [106]: %timeit c = np.repeat(b[:, newaxis], 100, axis=1)
1000 loops, best of 3: 347 µs per loop

In [107]: %timeit c = np.array([b,]*100).transpose()
100 loops, best of 3: 5.56 ms per loop

about 15 times faster using broadcast


np.broadcast_to is even faster than np.tile:

x = np.arange(9)

%timeit np.broadcast_to(x, (6,9))
100000 loops, best of 3: 3.6 µs per loop

%timeit np.tile(x, (6,1))
100000 loops, best of 3: 8.4 µs per loop

But fastest is @tom10's method:

%timeit np.repeat(x[np.newaxis, :], 6, axis=0) 
100000 loops, best of 3: 3.15 µs per loop

You can use

np.tile(x,3).reshape((4,3))

tile will generate the reps of the vector

and reshape will give it the shape you want


One clean solution is to use NumPy's outer-product function with a vector of ones:

np.outer(np.ones(n), x)

gives n repeating rows. Switch the argument order to get repeating columns. To get an equal number of rows and columns you might do

np.outer(np.ones_like(x), x)

import numpy as np
x=np.array([1,2,3])
y=np.multiply(np.ones((len(x),len(x))),x).T
print(y)

yields:

[[ 1.  1.  1.]
 [ 2.  2.  2.]
 [ 3.  3.  3.]]

참고URL : https://stackoverflow.com/questions/1550130/cloning-row-or-column-vectors

반응형