¿Cuál es el equivalente de repmat de MATLAB en NumPy?

103

Me gustaría ejecutar el equivalente al siguiente código de MATLAB usando NumPy: repmat([1; 1], [1 1 1]). ¿Cómo lograría esto?

vernomcrp
fuente

Respuestas:

103

Aquí hay un enlace de NumPy (oficial) mucho mejor para usuarios de Matlab : me temo que el de mathesaurus está bastante desactualizado.

El equivalente numérico de repmat(a, m, n)es tile(a, (m, n)).

Esto funciona con múltiples dimensiones y da un resultado similar a matlab. (Numpy ofrece una matriz de salida 3d como era de esperar; matlab, por alguna razón, ofrece una salida 2d, pero el contenido es el mismo).

Matlab:

>> repmat([1;1],[1,1,1])

ans =
     1
     1

Pitón:

In [46]: a = np.array([[1],[1]])
In [47]: np.tile(a, [1,1,1])
Out[47]: 
array([[[1],
        [1]]])
robince
fuente
2
cuando intento el tamaño (repmat ([1; 1], [1,1,2])) obtengo ans = 2 1 2 [en matlab] pero en python np.tile (a, [1,1,2]) .forma que obtenga (1, 2, 2), quiero que el resultado de numpy sea el mismo que en matlab
vernomcrp
2
np.tile (a [:, np.newaxis], [1,1,2]) - da lo mismo. El problema es que el mosaico asciende aa la dimensión del argumento mosaico al agregar nuevos ejes cuando sea necesario. Matlab parece funcionar al revés. De manera similar, con el mosaico 4d necesitará newaxis dos veces ... así que np.tile(a[:,newaxis,newaxis],[1,2,3,4]) = size(repmat(a,[1 2 3 4]))según sea necesario ...
robince
17

Tenga en cuenta que algunas de las razones por las que necesitaría utilizar el repmat de MATLAB están a cargo del mecanismo de transmisión de NumPy , que le permite hacer varios tipos de matemáticas con matrices de forma similar. Entonces, si tuviera, digamos, una matriz de 1600x1400x3 que representa una imagen de 3 colores, podría (por elementos) multiplicarla por [1.0 0.25 0.25]para reducir la cantidad de verde y azul en cada píxel. Consulte el enlace anterior para obtener más información.

kwatford
fuente
2
No es que Matlab pueda hacer esta transmisión también, si usa bsxfun.
gerrit
8

Así es como lo entendí por un poco de jugueteo. Feliz de ser corregido y espero que esto ayude.

Digamos que tiene una matriz M de 2x3 elementos. Esto tiene dos dimensiones, obviamente.


No pude ver ninguna diferencia entre Matlab y Python mientras pedía manipular la matriz de entrada a lo largo de las dimensiones que la matriz ya tiene. Así, los dos mandamientos

repmat(M,m,n) % matlab

np.tile(M,(m,n)) # python

son realmente equivalentes para una matriz de rango 2 (dos dimensiones).


El asunto se vuelve contrario a la intuición cuando solicita la repetición / mosaico en más dimensiones de las que tiene la matriz de entrada. Volviendo a la matriz M de rango dos y forma 2x3, es suficiente observar lo que sucede con el tamaño / forma de la matriz de salida. Digamos que la secuencia de manipulación ahora es 1,1,2.

En Matlab

> size(repmat(M,1,1,2))
ans =

    2   3   2

ha copiado las dos primeras dimensiones (filas y columnas) de la matriz de entrada y lo ha repetido una vez en una nueva tercera dimensión (es decir, copiado dos veces). Fiel al nombrerepmat de la matriz de repetición.

En Python

>>> np.tile(M,(1,1,2)).shape
(1, 2, 6)

ha aplicado un procedimiento diferente ya que, supongo, la secuencia (1,1,2) se lee de manera diferente que en Matlab. El número de copias en la dirección de las columnas, filas y dimensión fuera del plano se lee de derecha a izquierda. El objeto resultante tiene una forma diferente a la de Matlab. Ya no se puede afirmar que repmaty tileson instrucciones equivalentes.


Para llegar tilea comportarse como repmat, en Python uno debe asegurarse de que la matriz de entrada tenga tantas dimensiones como elementos en la secuencia. Esto se hace, por ejemplo, mediante un pequeño preacondicionamiento y la creación de un objeto relacionado N

N = M[:,:,np.newaxis]

Entonces, en el lado de entrada uno tiene en N.shape = (2,3,1)lugar de M.shape = (2,3)y en el lado de salida

>>> np.tile(N,(1,1,2)).shape
(2, 3, 2)

cual fue la respuesta de size(repmat(M,1,1,2)) . Supongo que esto se debe a que hemos guiado a Python para que agregue la tercera dimensión a la derecha de (2,3) en lugar de a su izquierda, de modo que Python resuelve la secuencia (1,1,2) como se pretendía en Matlab. forma de leerlo.

El elemento en [:,:,0]en la respuesta Python para N contendrá los mismos valores que el elemento de (:,:,1)la respuesta Matlab para M .


Finalmente, parece que no puedo encontrar un equivalente para repmatcuando uno usa el producto Kronecker fuera de

>>> np.kron(np.ones((1,1,2)),M).shape
(1, 2, 6)

a menos que luego precondicione M en N como se indicó anteriormente. Así que yo diría que la forma más general de avanzar es utilizar las formas de np.newaxis.


El juego se vuelve más complicado cuando consideramos una matriz L de rango 3 (tres dimensiones) y el simple caso de que no se agreguen nuevas dimensiones en la matriz de salida. Estas dos instrucciones aparentemente equivalentes no producirán los mismos resultados

repmat(L,p,q,r) % matlab

np.tile(L,(p,q,r)) # python

porque las direcciones de fila, columna, fuera del plano son (p, q, r) en Matlab y (q, r, p) en Python, que no era visible con matrices de rango 2. Allí, hay que tener cuidado y obtener los mismos resultados con los dos idiomas requeriría más preacondicionamiento.


Soy consciente de que es posible que este razonamiento no sea general, pero solo podría resolverlo hasta aquí. Con suerte, esto invita a otros becarios a someterlo a una prueba más dura.

XavierStuvw
fuente
6

Conozca ambos tiley repeat.

x = numpy.arange(5)
print numpy.tile(x, 2)
print x.repeat(2)
Steve Tjoa
fuente
1

numpy.matlib tiene una función repmat con una interfaz similar a la función matlab

from numpy.matlib import repmat
repmat( np.array([[1],[1]]) , 1, 1)
e-malito
fuente
0
>>> import numpy as np

>>> np.repeat(['a','b'], [2,5])

array(['a', 'a', 'b', 'b', 'b', 'b', 'b'], dtype='<U1')

>>> np.repeat([1,2], [2,5])

array([1, 1, 2, 2, 2, 2, 2])

>>> np.repeat(np.array([1,2]), [3]).reshape(2,3)

array([[1, 1, 1],
       [2, 2, 2]])

>>> np.repeat(np.array([1,2]), [2,4]).reshape(3,2)

array([[1, 1],
       [2, 2],
       [2, 2]])

>>> np.repeat(np.matrix('1 2; 3 4'), [2]).reshape(4,2)

matrix([[1, 1],
        [2, 2],
        [3, 3],
        [4, 4]])
Shivid
fuente