"Клонирование" векторов строк или столбцов
иногда полезно "клонировать" вектор строки или столбца в матрицу. Под клонированием я подразумеваю преобразование вектора строки, такого как
[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.]])
почему не работал первый метод (в[16])? Есть как достичь этой задачи в python более элегантным способом?
7 ответов:
вот элегантный, Питонический способ сделать это:
>>> 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]])
во-первых, обратите внимание, что в пакете numpy в вещания операции обычно нет необходимости дублировать строки и столбцы. Смотрите этой и этой для описания.
но чтобы сделать это,повторить и newaxis вероятно, лучший способ
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]])
этот пример для вектора строки, но применение этого к вектору столбца, надеюсь, очевидно. повторите, кажется, заклинание это хорошо, но вы также можете сделать это с помощью умножения, как в вашем примере
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.]])
Я думаю, что использование трансляции в numpy является лучшим, и быстрее
Я сделал сравнение следующим образом
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
примерно в 15 раз быстрее с помощью broadcast
np.broadcast_to
- это даже быстрее, чем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
но самый быстрый метод @tom10:
%timeit np.repeat(x[np.newaxis, :], 6, axis=0) 100000 loops, best of 3: 3.15 µs per loop