Qual é o equivalente do repmat do MATLAB em NumPy


103

Eu gostaria de executar o equivalente do código MATLAB seguir usando NumPy: repmat([1; 1], [1 1 1]). Como eu faria isso?

Respostas:


103

Aqui está um link NumPy (oficial) muito melhor para usuários do Matlab - temo que o do mathesaurus esteja bastante desatualizado.

O equivalente numpy de repmat(a, m, n)é tile(a, (m, n)).

Isso funciona com várias dimensões e dá um resultado semelhante ao matlab. (Numpy fornece uma matriz de saída 3D como você esperaria - o matlab por algum motivo fornece uma saída 2d - mas o conteúdo é o mesmo).

Matlab:

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

ans =
     1
     1

Pitão:

In [46]: a = np.array([[1],[1]])
In [47]: np.tile(a, [1,1,1])
Out[47]: 
array([[[1],
        [1]]])

2
quando tento size (repmat ([1; 1], [1,1,2])) ele obtém ans = 2 1 2 [em matlab], mas em python np.tile (a, [1,1,2]) .formar obter (1, 2, 2), quero numpy dar o resultado igual ao matlab
vernomcrp

2
np.tile (a [:, np.newaxis], [1,1,2]) - dá o mesmo. O problema é que o bloco promove aa dimensão do argumento bloco acrescentando novos eixos conforme necessário. O Matlab parece funcionar de outra maneira. Da mesma forma, com tiling 4d, você precisará de um novo eixo duas vezes ... np.tile(a[:,newaxis,newaxis],[1,2,3,4]) = size(repmat(a,[1 2 3 4]))conforme necessário ...
robince

17

Observe que alguns dos motivos pelos quais você precisaria usar o repmat do MATLAB são atendidos pelo mecanismo de transmissão do NumPy , que permite fazer vários tipos de matemática com matrizes de formato semelhante. Portanto, se você tivesse, digamos, uma matriz de 1600 x 1400 x 3 representando uma imagem de três cores, você poderia (elemento a elemento) multiplicá-la [1.0 0.25 0.25]para reduzir a quantidade de verde e azul em cada pixel. Veja o link acima para mais informações.


2
Não que o Matlab possa fazer essa transmissão também, se você usar bsxfun.
gerrit


8

Foi assim que eu entendi, mexendo um pouco. Fico feliz em ser corrigido e espero que isso ajude.

Digamos que você tenha uma matriz M de 2x3 elementos. Isso tem duas dimensões, obviamente.


Não pude ver nenhuma diferença entre Matlab e Python ao pedir para manipular a matriz de entrada ao longo das dimensões que a matriz já possui. Assim, os dois comandos

repmat(M,m,n) % matlab

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

são realmente equivalentes para uma matriz de classificação 2 (duas dimensões).


A questão fica contra-intuitiva quando você pede repetição / agrupamento em mais dimensões do que a matriz de entrada possui. Voltando à matriz M de classificação dois e forma 2x3, é suficiente observar o que acontece com o tamanho / formato da matriz de saída. Digamos que a sequência de manipulação agora seja 1,1,2.

Em Matlab

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

    2   3   2

ele copiou as primeiras duas dimensões (linhas e colunas) da matriz de entrada e repetiu isso uma vez em uma nova terceira dimensão (copiado duas vezes, isto é). Fiel à nomenclatura repmatda matriz de repetição.

Em Python

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

aplicou um procedimento diferente, uma vez que, presumo, a sequência (1,1,2) é lida de forma diferente do que no Matlab. O número de cópias na direção das colunas, linhas e dimensão fora do plano estão sendo lidos da direita para a esquerda. O objeto resultante tem uma forma diferente do Matlab. Não se pode mais afirmar isso repmate tilesão instruções equivalentes.


Para conseguir tilese comportar como repmat, em Python, é preciso ter certeza de que a matriz de entrada tem tantas dimensões quanto os elementos estão na sequência. Isso é feito, por exemplo, por um pequeno pré-condicionamento e criação de um objeto relacionado N

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

Então, no lado da entrada um tem N.shape = (2,3,1)ao invés M.shape = (2,3)e no lado da saída

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

qual foi a resposta de size(repmat(M,1,1,2)). Presumo que seja porque guiamos Python para adicionar a terceira dimensão à direita de (2,3) em vez de à sua esquerda, de modo que Python resolva a sequência (1,1,2) como foi planejado no Matlab maneira de lê-lo.

O elemento [:,:,0]em resposta a Python para N irá conter os mesmos valores que o elemento (:,:,1)da resposta Matlab para M .


Finalmente, não consigo encontrar um equivalente para repmatquando se usa o produto Kronecker de

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

a menos que eu pré-condicione M em N como acima. Portanto, eu diria que a maneira mais geral de seguir em frente é usar os meios de np.newaxis.


O jogo fica mais complicado quando consideramos uma matriz L de classificação 3 (três dimensões) e o simples caso de nenhuma nova dimensão sendo adicionada na matriz de saída. Essas duas instruções aparentemente equivalentes não produzirão os mesmos resultados

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

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

porque as direções de linha, coluna e fora do plano são (p, q, r) no Matlab e (q, r, p) no Python, o que não era visível com matrizes de classificação 2. Nesse caso, é preciso ter cuidado e obter os mesmos resultados com as duas línguas exigiria mais pré-condicionamentos.


Estou ciente de que esse raciocínio pode não ser geral, mas só poderia resolvê-lo até aqui. Esperançosamente, isso convida outros companheiros a fazer um teste mais difícil.


6

Conheça ambos tilee repeat.

x = numpy.arange(5)
print numpy.tile(x, 2)
print x.repeat(2)

1

numpy.matlib tem uma função repmat com uma interface semelhante à função matlab

from numpy.matlib import repmat
repmat( np.array([[1],[1]]) , 1, 1)

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]])
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.