Domanda

Qualcuno ha mai riscontrato questo problema? Supponiamo che tu abbia due array come il seguente

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

C'è un modo per confrontare quali elementi in a esistono in b? Ad esempio,

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

Sto cercando di evitare i loop in quanto richiederebbe secoli con milioni di elementi. Qualche idea?

Saluti

È stato utile?

Soluzione

In realtà, esiste una soluzione ancora più semplice di una di queste:

import numpy as np

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

c = np.in1d(a,b)

La c risultante è quindi:

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

Altri suggerimenti

Usa 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]

Nota che np.intersect1d dà la risposta sbagliata se a o b hanno elementi non unici. In tal caso utilizzare np.intersect1d_nu.

Esistono anche np.setdiff1d, setxor1d, setmember1d e union1d. Vedere Elenco di esempi Numpy con Doc

Grazie per la risposta kaizer.se. Non è proprio quello che stavo cercando, ma con il suggerimento di un amico e quello che hai detto, ho pensato a quanto segue.

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

È un processo un po 'complicato, ma batte la scrittura di loop o l'utilizzo di weave con loop.

Saluti

Numpy ha una funzione set numpy.setmember1d () che funziona su array ordinati e unificati e restituisce esattamente l'array booleano che si desidera. Se gli array di input non corrispondono ai criteri, dovrai convertirlo nel formato impostato e invertire la trasformazione sul risultato.

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]

Modifica: Sfortunatamente il metodo setmember1d in numpy è davvero inefficiente. La ricerca ordinata e il metodo di assegnazione che hai proposto funziona più velocemente, ma se puoi assegnarlo direttamente potresti anche assegnare direttamente il risultato ed evitare molte copie non necessarie. Inoltre il tuo metodo fallirà se b contiene qualcosa che non è in a. Quanto segue corregge tali errori:

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)

I miei benchmark mostrano questo a 91us contro 6,6ms per il tuo approccio e 109ms per set intorpidito1d su 1M elemento a e 100 elemento b.

ebresset, la tua risposta non funzionerà a meno che a è un sottoinsieme di b (e a e b sono ordinati). In caso contrario, la ricerca ordinata restituirà falsi indici. Ho dovuto fare qualcosa di simile e combinarlo con il tuo codice:

# 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)

Il tuo esempio implica un comportamento simile a un set, preoccupandosi più di esistenza nell'array che di avere l'elemento giusto nel posto giusto. Numpy lo fa diversamente con le sue matrici e matrici matematiche, ti dirà solo degli oggetti nel punto esatto giusto. Puoi farlo funzionare per te?

>>> import numpy
>>> a = numpy.array([1,2,3])
>>> b = numpy.array([1,3,3])
>>> a == b
array([ True, False,  True], dtype=bool)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top