2
votes

Obtenir des éléments à partir d'une matrice numpy, que les index sont dans un tableau

J'essaie de convertir un code matlab en python et j'ai été confronté à un code comme:

a.item(x) #python

cela obtient en fait des index de b et fait

a=[1 2 3;4 5 6;7 8 9]
b=[1, 4, 8]
a(b)
//output :
ans :
1   4   8


2 commentaires

Probablement un double de Comment puis-je comparer deux listes en python et renvoyer les correspondances . Désolé de ne pas savoir comment définir une question comme doublon d'une autre.


@Chunpin Non, ce n'est pas le même problème. De plus, a (b) donne et = 1 2 6 .


3 Réponses :


2
votes

Attention: au moment de rédiger cette réponse, l'exemple donné dans la question est faux. a (b) entraînerait:

import numpy as np

a = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
b = np.array([0, 3, 7])

c = a[np.unravel_index(b, a.shape, 'F')]

print(a)
print(b)
print(c)

[[10 20 30]
 [40 50 60]
 [70 80 90]]

[0 3 7]

[10 20 60]

Le code MATLAB fourni utilise indexation linéaire , qui utilise l'ordre des colonnes principales, alors que le a.item (x) Python indiqué utilise l'ordre des lignes principales.

La ind2sub La fonction MATLAB peut convertir des indices linéaires en indices de tableau. Une fonction numpy similaire est unravel_index .

Jetons un œil à l'exemple de code suivant. Attention: Python utilise une indexation basée sur 0 alors que MATLAB utilise une indexation basée sur 1.

ans =
   1   2   6


0 commentaires

0
votes

Dans une session Octave:

In [75]: np.unravel_index(b, (3,3))                                                                      
Out[75]: (array([0, 1, 2]), array([0, 0, 1]))
In [76]: a[_]                    # using the Out[75] line as index                                                                        
Out[76]: array([1, 2, 6])
In [77]: a[0,0],a[1,0],a[2,1]            # equivalently                                                                
Out[77]: (1, 2, 6)

Ce n'est pas le genre de comportement que je me souviens avoir dans MATLAB, mais je n'ai pas l'habitude d'utiliser des valeurs d'index supérieures à dimensions. Il s'agit évidemment de sélectionner les éléments dans une matrice aplatie

>> [r,c] = ind2sub([3,3],b)
r =

   1   1   2

c =

   1   2   3

>> a(1,1), a(1,2), a(2,3)
ans =  1
ans =  2
ans =  6

En Python / numpy, l'indexation se fait avec [] au lieu de () . Il est également basé sur 0, et non sur 1.

In [67]: a = np.arange(1,10).reshape(3,3,order='F')                                                      
In [68]: a                                                                                               
Out[68]: 
array([[1, 4, 7],
       [2, 5, 8],
       [3, 6, 9]])
In [69]: a.flat[b]                                                                                       
Out[69]: array([1, 2, 6])

Pour obtenir les mêmes valeurs dans numpy , j'ai dû spécifier order F code > lors de l'aplatissement du tableau. De cette façon, il «scanne» les valeurs dans l'ordre majeur de colonne utilisé par MATLAB.

Sans order F , l'ordre d'analyse par défaut est la ligne principale:

In [61]: a.ravel()                                                                                       
Out[61]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
In [62]: a.ravel()[b]                                                                                    
Out[62]: array([1, 4, 8])

Je pourrais également obtenir la commande F lors du remodelage initial de a:

In [56]: a = np.arange(1,10).reshape(3,3)                                                                
In [57]: a                                                                                               
Out[57]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In [58]: b=[0,3,7]                                                                                       
In [59]: a.ravel(order='F')[b]                                                                           
Out[59]: array([1, 2, 6])
In [60]: a.ravel(order='F')                                                                              
Out[60]: array([1, 4, 7, 2, 5, 8, 3, 6, 9])

===

Dans MATLAB / Octave, on peut obtenir les indices 2d avec:

>> reshape(a,1,9)
ans =

   1   4   7   2   5   8   3   6   9

>> reshape(a,1,9)(b)
ans =

   1   2   6

Le même démêlage en numpy (appliqué à la version de la commande F de a):

>> a=[1 2 3;4 5 6;7 8 9]
a =

   1   2   3
   4   5   6
   7   8   9

>> b=[1, 4, 8]
b =

   1   4   8

>> a(b)
ans =

   1   2   6


0 commentaires

1
votes

Utilisez numpy
  • Aplatissez d'abord votre tableau 2D en 1D
  • Utilisez ensuite l'index dans b pour rechercher des données dans a
  • Remarque: l'index en python commence à partir de 0 matlab est 1 , vous devez donc réduire les indices en b de 1
    import numpy as np

    a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    a = a.flatten()
    b = np.array([1, 4, 8])
    
    print(a[b-1])

    #array([1, 4, 8])


3 commentaires

L'indexation linéaire MATLAB utilise l'ordre principal des colonnes, tandis que votre solution utilise l'ordre principal des lignes. Malheureusement, l'exemple donné dans la question est déjà faux sur cette partie.


@HansHirse Que voulez-vous dire par l'exemple donné est faux sur cette partie? Vous pensiez que c'était le même résultat qu'il voulait reproduire en python? pas seulement un exemple


S'il vous plaît voir mon commentaire sur la question: a (b) renvoie 1 2 6 , et non 1 4 8 comme indiqué par l'interlocuteur. Donc, en fin de compte, il n'est pas clair si l'auteur veut imiter le fonctionnement (correct) de MATLAB (indexation de l'ordre principal des colonnes), ou l'indexation de l'ordre des lignes principales données, ce qui ne serait alors pas la bonne manière MATLAB.