Pregunta

¿Alguien se ha topado con este problema? Digamos que tienes dos matrices como las siguientes

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

¿Hay una manera de comparar qué elementos en a existen en b? Por ejemplo,

c = a == b # Wishful example here
print c
array([1,4,5])
# Or even better
array([True, False, False, True, True, False])

Estoy tratando de evitar los bucles, ya que llevaría siglos con millones de elementos. ¿Algunas ideas?

Saludos

¿Fue útil?

Solución

En realidad, hay una solución aún más simple que cualquiera de estas:

import numpy as np

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

c = np.in1d(a,b)

La c resultante es entonces:

array([ True, False, False,  True,  True, False], dtype=bool)

Otros consejos

Utilice np.intersect1d.

#!/usr/bin/env python
import numpy as np
a = np.array([1,2,3,4,5,6])
b = np.array([1,4,5])
c=np.intersect1d(a,b)
print(c)
# [1 4 5]

Tenga en cuenta que np.intersect1d da la respuesta incorrecta si a o b tienen elementos no únicos. En ese caso usar np.intersect1d_nu.

También hay np.setdiff1d, setxor1d, setmember1d y union1d. Ver Lista de ejemplos desiguales con Doc

Gracias por su respuesta kaizer.se. No es exactamente lo que estaba buscando, pero con una sugerencia de un amigo y lo que dijiste, se me ocurrió lo siguiente.

import numpy as np

a = np.array([1,4,5]).astype(np.float32)
b = np.arange(10).astype(np.float32)

# Assigning matching values from a in b as np.nan
b[b.searchsorted(a)] = np.nan

# Now generating Boolean arrays
match = np.isnan(b)
nonmatch = match == False

Es un proceso un tanto engorroso, pero es mejor que escribir bucles o usar el tejido con bucles.

Saludos

Numpy tiene una función de conjunto numpy.setmember1d () que funciona en arreglos ordenados y sin etiquetar y devuelve exactamente el arreglo booleano que desea. Si las matrices de entrada no coinciden con los criterios, deberá convertirlos al formato establecido e invertir la transformación en el resultado.

import numpy as np
a = np.array([6,1,2,3,4,5,6])
b = np.array([1,4,5])

# convert to the uniqued form
a_set, a_inv = np.unique1d(a, return_inverse=True)
b_set = np.unique1d(b)
# calculate matching elements
matches = np.setmea_set, b_set)
# invert the transformation
result = matches[a_inv]
print(result)
# [False  True False False  True  True False]

Editar: Desafortunadamente, el método setmember1d en numpy es realmente ineficiente. El método de búsqueda ordenado y de asignación que propuso funciona más rápido, pero si puede asignarlo directamente, también puede asignarlo directamente al resultado y evitar una gran cantidad de copias innecesarias. También su método fallará si b contiene algo que no esté en a. Lo siguiente corrige esos errores:

result = np.zeros(a.shape, dtype=np.bool)
idxs = a.searchsorted(b)
idxs = idxs[np.where(idxs < a.shape[0])] # Filter out out of range values
idxs = idxs[np.where(a[idxs] == b)] # Filter out where there isn't an actual match
result[idxs] = True
print(result)

Mis puntos de referencia muestran esto en 91us vs. 6.6ms para su aproximación y 109ms para numpy setmember1d en 1M elemento a y 100 elemento b.

ebresset, su respuesta no funcionará a menos que a es un subconjunto de b (y a y b están ordenados). De lo contrario, el resultado de la búsqueda devolverá índices falsos. Tuve que hacer algo similar, y combinando eso con tu código:

# Assume a and b are sorted
idxs = numpy.mod(b.searchsorted(a),len(b))
idxs = idxs[b[idxs]==a]
b[idxs] = numpy.nan
match = numpy.isnan(b)

Su ejemplo implica un comportamiento similar a un conjunto, preocupándose más por la existencia de en la matriz que por tener el elemento correcto en el lugar correcto. Numpy hace esto de manera diferente con sus matrices y matrices matemáticas, solo le informará sobre los elementos en el lugar exacto correcto. ¿Puedes hacer que eso funcione para ti?

>>> import numpy
>>> a = numpy.array([1,2,3])
>>> b = numpy.array([1,3,3])
>>> a == b
array([ True, False,  True], dtype=bool)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top