56 votes

Obtenez des lignes qui se croisent sur deux tableaux numpy 2D

Je veux obtenir les lignes (communes) qui se croisent sur deux tableaux numpy 2D. Par exemple, si les tableaux suivants sont passés en entrées :

 array([[1, 4],
       [2, 5],
       [3, 6]])

array([[1, 4],
       [3, 6],
       [7, 8]])

la sortie doit être :

 array([[1, 4],
       [3, 6])

Je sais comment faire cela avec des boucles. Je cherche un moyen Pythonic/Numpy de le faire.

53voto

Joe Kington Points 68089

Pour les tableaux courts, utiliser des ensembles est probablement le moyen le plus clair et le plus lisible de le faire.

Une autre méthode consiste à utiliser numpy.intersect1d . Vous devrez cependant le tromper en traitant les lignes comme une valeur unique... Cela rend les choses un peu moins lisibles...

 import numpy as np

A = np.array([[1,4],[2,5],[3,6]])
B = np.array([[1,4],[3,6],[7,8]])

nrows, ncols = A.shape
dtype={'names':['f{}'.format(i) for i in range(ncols)],
       'formats':ncols * [A.dtype]}

C = np.intersect1d(A.view(dtype), B.view(dtype))

# This last bit is optional if you're okay with "C" being a structured array...
C = C.view(A.dtype).reshape(-1, ncols)

Pour les grands tableaux, cela devrait être considérablement plus rapide que d'utiliser des ensembles.

23voto

mtrw Points 10098

Vous pouvez utiliser les ensembles de Python :

 >>> import numpy as np
>>> A = np.array([[1,4],[2,5],[3,6]])
>>> B = np.array([[1,4],[3,6],[7,8]])
>>> aset = set([tuple(x) for x in A])
>>> bset = set([tuple(x) for x in B])
>>> np.array([x for x in aset & bset])
array([[1, 4],
       [3, 6]])

Comme le souligne Rob Cowie, cela peut être fait de manière plus concise en

 np.array([x for x in set(tuple(x) for x in A) & set(tuple(x) for x in B)])

Il existe probablement un moyen de le faire sans tous les allers-retours des tableaux aux tuples, mais cela ne me vient pas pour le moment.

5voto

Ram Kumar Karn Points 51

Une autre façon d'y parvenir en utilisant un tableau structuré :

 >>> a = np.array([[3, 1, 2], [5, 8, 9], [7, 4, 3]])
>>> b = np.array([[2, 3, 0], [3, 1, 2], [7, 4, 3]])
>>> av = a.view([('', a.dtype)] * a.shape[1]).ravel()
>>> bv = b.view([('', b.dtype)] * b.shape[1]).ravel()
>>> np.intersect1d(av, bv).view(a.dtype).reshape(-1, a.shape[1])
array([[3, 1, 2],
       [7, 4, 3]])

Pour plus de clarté, la vue structurée ressemble à ceci :

 >>> a.view([('', a.dtype)] * a.shape[1])
array([[(3, 1, 2)],
       [(5, 8, 9)],
       [(7, 4, 3)]],
       dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8')])

2voto

Espoir Murhabazi Points 1434
np.array(set(map(tuple, b)).difference(set(map(tuple, a))))

Cela pourrait aussi fonctionner

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X