Qual è l'equivalente del repmat di MATLAB in NumPy


103

Vorrei eseguire l'equivalente del seguente codice MATLAB con NumPy: repmat([1; 1], [1 1 1]). Come potrei farlo?

Risposte:


103

Ecco un collegamento NumPy per utenti Matlab molto migliore (ufficiale) - Temo che quello del mathesaurus sia abbastanza obsoleto.

L'equivalente numpy di repmat(a, m, n)è tile(a, (m, n)).

Funziona con più dimensioni e fornisce un risultato simile a Matlab. (Numpy fornisce un array di output 3d come ci si aspetterebbe - matlab per qualche motivo fornisce un output 2d - ma il contenuto è lo stesso).

MATLAB:

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

ans =
     1
     1

Pitone:

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

2
quando provo size (repmat ([1; 1], [1,1,2])) ottiene ans = 2 1 2 [in matlab] ma in python np.tile (a, [1,1,2]) .shape it get (1, 2, 2), voglio che numpy dia il risultato uguale a matlab
vernomcrp

2
np.tile (a [:, np.newaxis], [1,1,2]) - dà lo stesso. Il problema è che tile promuove ala dimensione dell'argomento tile anteponendo nuovi assi se necessario. Matlab sembra funzionare nell'altro modo. Allo stesso modo, con la piastrellatura 4d avrai bisogno di newaxis due volte ... così np.tile(a[:,newaxis,newaxis],[1,2,3,4]) = size(repmat(a,[1 2 3 4]))come richiesto ...
robince

17

Nota che alcuni dei motivi per cui dovresti usare repmat di MATLAB sono risolti dal meccanismo di trasmissione di NumPy , che ti consente di fare vari tipi di matematica con array di forma simile. Quindi, se avessi, ad esempio, un array 1600x1400x3 che rappresenta un'immagine a 3 colori, potresti (elementwise) moltiplicarlo [1.0 0.25 0.25]per ridurre la quantità di verde e blu su ciascun pixel. Vedere il collegamento sopra per ulteriori informazioni.


2
Non che Matlab possa fare anche questa trasmissione, se usi bsxfun.
gerrit


8

Questo è come l'ho capito dopo aver giocato un po '. Felice di essere corretto e spero che questo aiuti.

Supponiamo di avere una matrice M di 2x3 elementi. Questo ha due dimensioni, ovviamente.


Non ho visto alcuna differenza tra Matlab e Python mentre chiedevo di manipolare la matrice di input lungo le dimensioni che la matrice ha già. Così i due comandi

repmat(M,m,n) % matlab

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

sono realmente equivalenti per una matrice di rango 2 (due dimensioni).


Le cose diventano controintuitive quando chiedi la ripetizione / piastrellatura su più dimensioni rispetto alla matrice di input. Tornando alla matrice M di rango due e di forma 2x3, è sufficiente guardare cosa succede alla dimensione / forma della matrice di output. Supponiamo che la sequenza per la manipolazione sia ora 1,1,2.

In Matlab

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

    2   3   2

ha copiato le prime due dimensioni (righe e colonne) della matrice di input e l'ha ripetuta una volta in una nuova terza dimensione (copiata due volte, cioè). Fedele alla denominazionerepmat per la matrice di ripetizione.

In Python

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

ha applicato una procedura diversa poiché, presumo, la sequenza (1,1,2) viene letta in modo diverso rispetto a Matlab. Il numero di copie nella direzione di colonne, righe e dimensione fuori piano viene letto da destra a sinistra. L'oggetto risultante ha una forma diversa da Matlab. Non si può più affermare che repmate tilesono istruzioni equivalenti.


Per riuscire tilea comportarsi così repmat, in Python bisogna assicurarsi che la matrice di input abbia tante dimensioni quanti sono gli elementi nella sequenza. Ciò viene fatto, ad esempio, da un piccolo precondizionamento e dalla creazione di un oggetto correlato N

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

Quindi, sul lato di ingresso si ha N.shape = (2,3,1)piuttosto che M.shape = (2,3)e sul lato di uscita

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

che era la risposta di size(repmat(M,1,1,2)) . Presumo che ciò sia dovuto al fatto che abbiamo guidato Python ad aggiungere la terza dimensione a destra di (2,3) piuttosto che a sinistra, in modo che Python elabori la sequenza (1,1,2) come era intesa in Matlab modo di leggerlo.

L'elemento nella [:,:,0]risposta di Python per N conterrà gli stessi valori dell'elemento (:,:,1)risposta Matlab per M .


Infine, non riesco a trovare un equivalente per repmatquando si utilizza il prodotto Kronecker fuori

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

a meno che non precondizioni M in N come sopra. Quindi direi che il modo più generale per andare avanti è usare i modi di np.newaxis.


Il gioco diventa più complicato se consideriamo una matrice L di rango 3 (tre dimensioni) e il semplice caso in cui non vengono aggiunte nuove dimensioni nella matrice di output. Queste due istruzioni apparentemente equivalenti non produrranno gli stessi risultati

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

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

perché la riga, la colonna, le direzioni fuori dal piano sono (p, q, r) in Matlab e (q, r, p) in Python, che non erano visibili con gli array di rango 2. Lì bisogna stare attenti e ottenere gli stessi risultati con le due lingue richiederebbe più precondizionamenti.


Sono consapevole che questo ragionamento potrebbe non essere generale, ma potrei elaborarlo solo fino a questo punto. Si spera che questo inviti altri colleghi a metterlo a dura prova.


6

Conosci entrambi tilee repeat.

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

1

numpy.matlib ha una funzione repmat con un'interfaccia simile alla funzione 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]])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.