NumPy: Comparando elementos em duas matrizes
Pergunta
Alguém já vêm até este problema? Vamos dizer que você tem duas matrizes como o seguinte
a = array([1,2,3,4,5,6])
b = array([1,4,5])
Existe uma maneira de comparar o que elementos em um existir em b? Por exemplo,
c = a == b # Wishful example here
print c
array([1,4,5])
# Or even better
array([True, False, False, True, True, False])
Eu estou tentando evitar loops como levaria idades com milhões de elementos. Alguma ideia?
Felicidades
Solução
Na verdade, há uma solução ainda mais simples do que qualquer um destes:
import numpy as np
a = array([1,2,3,4,5,6])
b = array([1,4,5])
c = np.in1d(a,b)
O c resultante é então:
array([ True, False, False, True, True, False], dtype=bool)
Outras dicas
Use 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]
Note que np.intersect1d dá a resposta errada se a ou b têm elementos não exclusivos. Nesse caso de uso np.intersect1d_nu.
Há também np.setdiff1d, setxor1d, setmember1d e union1d. Vejo Exemplo Numpy Lista Com Doc
Obrigado por sua kaizer.se resposta. Não é bem o que eu estava procurando, mas com uma sugestão de um amigo e que você disse que eu vim com o seguinte.
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
É um pouco de um processo complicado, mas ele bate escrever laços ou usando tecer com loops.
Felicidades
Numpy tem uma numpy.setmember1d função set () que funciona em arrays e retornos classificados e uniqued exatamente a matriz booleana que você quer. Se os arrays dados não coincidem com os critérios que você precisa para converter para o formato do conjunto e inverta a transformação no 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]
Edit: Infelizmente o método setmember1d em numpy é realmente ineficiente. A pesquisa ordenados e método de atribuir-lhe proposto funciona mais rápido, mas se você pode atribuir diretamente assim como você pode atribuir diretamente para o resultado e evitar lotes de cópias desnecessárias. Também o seu método irá falhar se b contém nada que não seja em um. A seguir corrige esses erros:
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)
Os meus benchmarks mostram isso em 91us vs. 6.6ms para sua abordagem e 109ms para setmember1d numpy em 1M elemento de um e 100 elemento b.
ebresset, sua resposta não funcionará a menos um é um subconjunto de b (e a e b são classificados). Caso contrário, o searchsorted voltará índices falsos. Eu tinha que fazer algo semelhante, e que combina com o seu 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)
Seu exemplo implica definir-como comportamento, cuidar mais sobre existência na matriz do que ter o elemento certo no lugar certo. Numpy faz isso de forma diferente, com suas matrizes matemáticas e matrizes, ele irá dizer-lhe apenas cerca de itens no ponto certo exato. você pode fazer esse trabalho para você?
>>> import numpy
>>> a = numpy.array([1,2,3])
>>> b = numpy.array([1,3,3])
>>> a == b
array([ True, False, True], dtype=bool)