verifica si la matriz numpy es un subconjunto de otra matriz

Ya se han hecho preguntas similares en SO, pero tienen restricciones más específicas y sus respuestas no se aplican a mi pregunta.

En términos generales, ¿cuál es la forma más python de determinar si una matriz de números arbitrarios es un subconjunto de otra matriz? Más específicamente, tengo una matriz de aproximadamente 20000×3 y necesito conocer los índices de los elementos 1×3 que están completamente contenidos dentro de un conjunto. De manera más general, hay una forma más pythonica de escribir lo siguiente:

master=[12,155,179,234,670,981,1054,1209,1526,1667,1853] #some indices of interest triangles=np.random.randint(2000,size=(20000,3)) #some data for i,x in enumerate(triangles): if x[0] in master and x[1] in master and x[2] in master: print i 

Para mi caso de uso, puedo asumir con seguridad que len (maestro) << 20000. (En consecuencia, también es seguro asumir que el maestro está ordenado porque es barato).

Puede hacer esto fácilmente mediante la iteración sobre una matriz en la comprensión de lista. Un ejemplo de juguete es el siguiente:

 import numpy as np x = np.arange(30).reshape(10,3) searchKey = [4,5,8] x[[0,3,7],:] = searchKey x 

da

  array([[ 4, 5, 8], [ 3, 4, 5], [ 6, 7, 8], [ 4, 5, 8], [12, 13, 14], [15, 16, 17], [18, 19, 20], [ 4, 5, 8], [24, 25, 26], [27, 28, 29]]) 

Ahora iterar sobre los elementos:

 ismember = [row==searchKey for row in x.tolist()] 

El resultado es

 [True, False, False, True, False, False, False, True, False, False] 

Puedes modificarlo por ser un subconjunto como en tu pregunta:

 searchKey = [2,4,10,5,8,9] # Add more elements for testing setSearchKey = set(searchKey) ismember = [setSearchKey.issuperset(row) for row in x.tolist()] 

Si necesitas los índices, entonces usa

 np.where(ismember)[0] 

Da

 array([0, 3, 7]) 

Aquí hay dos enfoques que puedes probar:

1, utilizar conjuntos. Los conjuntos se implementan de forma muy similar a los diccionarios de Python y tienen búsquedas de tiempo constante. Se parecería mucho al código que ya tiene, solo cree un conjunto desde el maestro:

 master = [12,155,179,234,670,981,1054,1209,1526,1667,1853] master_set = set(master) triangles = np.random.randint(2000,size=(20000,3)) #some data for i, x in enumerate(triangles): if master_set.issuperset(x): print i 

2, Utilice la búsqueda ordenada. Esto es bueno porque no requiere que uses tipos de hashable y usa números incorporados. searchsorted es log (N) en el tamaño del maestro y O (N) en el tamaño de los triangeles, por lo que también debería ser bastante rápido, tal vez más rápido dependiendo del tamaño de sus arreglos y demás.

 master = [12,155,179,234,670,981,1054,1209,1526,1667,1853] master = np.asarray(master) triangles = np.random.randint(2000,size=(20000,3)) #some data idx = master.searchsorted(triangles) idx.clip(max=len(master) - 1, out=idx) print np.where(np.all(triangles == master[idx], axis=1)) 

Este segundo caso supone que el maestro está ordenado, como implica searchsorted .