Quel est l'équivalent du repmat de MATLAB dans NumPy


103

Je voudrais exécuter l'équivalent du code Matlab suivant à l' aide NumPy: repmat([1; 1], [1 1 1]). Comment pourrais-je accomplir cela?

Réponses:


103

Voici un bien meilleur lien (officiel) NumPy pour les utilisateurs de Matlab - J'ai bien peur que celui de mathesaurus soit assez obsolète.

L'équivalent numpy de repmat(a, m, n)est tile(a, (m, n)).

Cela fonctionne avec plusieurs dimensions et donne un résultat similaire à matlab. (Numpy donne un tableau de sortie 3D comme on peut s'y attendre - matlab pour une raison quelconque donne une sortie 2D - mais le contenu est le même).

Matlab:

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

ans =
     1
     1

Python:

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

2
quand j'essaye size (repmat ([1; 1], [1,1,2])) il obtient ans = 2 1 2 [dans matlab] mais en python np.tile (a, [1,1,2]) .shape it get (1, 2, 2), je veux numpy donner le même résultat que matlab
vernomcrp

2
np.tile (a [:, np.newaxis], [1,1,2]) - il donne la même chose. Le problème est que la tuile promeut ala dimension de l'argument tuile en ajoutant de nouveaux axes si nécessaire. Matlab semble fonctionner dans l'autre sens. De même, avec le carrelage 4d, vous aurez besoin de newaxis deux fois ... donc si np.tile(a[:,newaxis,newaxis],[1,2,3,4]) = size(repmat(a,[1 2 3 4]))nécessaire ...
robince

17

Notez que certaines des raisons pour lesquelles vous auriez besoin d'utiliser le repmat de MATLAB sont prises en charge par le mécanisme de diffusion de NumPy , qui vous permet de faire différents types de mathématiques avec des tableaux de forme similaire. Donc, si vous aviez, par exemple, un tableau de 1 600 x 1 400 x 3 représentant une image à 3 couleurs, vous pourriez (par élément) le multiplier par [1.0 0.25 0.25]pour réduire la quantité de vert et de bleu à chaque pixel. Voir le lien ci-dessus pour plus d'informations.


2
Non pas que Matlab puisse également faire cette diffusion, si vous utilisez bsxfun.
gerrit


8

C'est ainsi que je l'ai compris après un peu de tripotage. Heureux d'être corrigé et j'espère que cela aidera.

Supposons que vous ayez une matrice M de 2x3 éléments. Cela a deux dimensions, évidemment.


Je ne voyais aucune différence entre Matlab et Python en demandant de manipuler la matrice d'entrée selon les dimensions que la matrice a déjà. Ainsi les deux commandes

repmat(M,m,n) % matlab

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

sont vraiment équivalentes pour une matrice de rang 2 (deux dimensions).


Les choses deviennent contre-intuitives lorsque vous demandez une répétition / une mosaïque sur plus de dimensions que la matrice d'entrée. Pour en revenir à la matrice M de rang deux et de forme 2x3, il suffit de regarder ce qu'il advient de la taille / forme de la matrice de sortie. Disons que la séquence de manipulation est maintenant 1,1,2.

Dans Matlab

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

    2   3   2

il a copié les deux premières dimensions (lignes et colonnes) de la matrice d'entrée et l'a répétée une fois dans une nouvelle troisième dimension (copiée deux fois, c'est-à-dire). Fidèle à la dénomination repmatde la matrice de répétition.

En Python

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

il a appliqué une procédure différente puisque, je présume, la séquence (1,1,2) est lue différemment que dans Matlab. Le nombre de copies dans le sens des colonnes, des lignes et de la dimension hors plan est lu de droite à gauche. L'objet résultant a une forme différente de Matlab. On ne peut plus affirmer cela repmatet ce tilesont des instructions équivalentes.


Pour arriver tileà se comporter comme repmat, en Python, il faut s'assurer que la matrice d'entrée a autant de dimensions que les éléments de la séquence. Cela se fait, par exemple, par un petit préconditionnement et la création d'un objet associé N

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

Ensuite, du côté entrée, on a N.shape = (2,3,1)plutôt que M.shape = (2,3)du côté sortie

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

qui était la réponse de size(repmat(M,1,1,2)). Je présume que c'est parce que nous avons guidé Python pour ajouter la troisième dimension à droite de (2,3) plutôt qu'à sa gauche, afin que Python élabore la séquence (1,1,2) comme prévu dans le Matlab manière de le lire.

L'élément [:,:,0]de la réponse Python pour N contiendra les mêmes valeurs que l'élément de (:,:,1)la réponse Matlab pour M .


Enfin, je n'arrive pas à trouver un équivalent pour repmatquand on utilise le produit Kronecker hors de

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

sauf si je préconditionne alors M en N comme ci-dessus. Je dirais donc que la manière la plus générale de passer à autre chose est d'utiliser les moyens de np.newaxis.


Le jeu devient plus délicat quand on considère une matrice L de rang 3 (trois dimensions) et le cas simple où aucune nouvelle dimension n'est ajoutée dans la matrice de sortie. Ces deux instructions apparemment équivalentes ne produiront pas les mêmes résultats

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

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

car les directions de ligne, de colonne, hors plan sont (p, q, r) dans Matlab et (q, r, p) en Python, ce qui n'était pas visible avec les tableaux de rang 2. Là, il faut être prudent et obtenir les mêmes résultats avec les deux langues demanderait plus de préconditionnement.


Je suis conscient que ce raisonnement n'est peut-être pas général, mais je ne pourrais y arriver que jusqu'ici. Espérons que cela invite d'autres camarades à le soumettre à un test plus difficile.


6

Sachez à la fois tileet repeat.

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

1

numpy.matlib a une fonction repmat avec une interface similaire à la fonction 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]])
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.