Come determinare se una colonna Panda contiene un valore particolare


157

Sto cercando di determinare se esiste una voce in una colonna Panda con un valore particolare. Ho provato a farlo con if x in df['id']. Pensavo che funzionasse, tranne quando gli ho dato un valore che sapevo non fosse nella colonna che 43 in df['id']è tornato True. Quando eseguo il sottoinsieme di un frame di dati contenente solo voci corrispondenti all'ID mancante df[df['id'] == 43], ovviamente non ci sono voci in esso. Come determinare se una colonna in un frame di dati Pandas contiene un valore particolare e perché il mio metodo attuale non funziona? (Cordiali saluti, ho lo stesso problema quando utilizzo l'implementazione in questa risposta a una domanda simile).

Risposte:


183

in di una serie controlla se il valore è nell'indice:

In [11]: s = pd.Series(list('abc'))

In [12]: s
Out[12]: 
0    a
1    b
2    c
dtype: object

In [13]: 1 in s
Out[13]: True

In [14]: 'a' in s
Out[14]: False

Un'opzione è vedere se ha valori univoci :

In [21]: s.unique()
Out[21]: array(['a', 'b', 'c'], dtype=object)

In [22]: 'a' in s.unique()
Out[22]: True

o un set di pitone:

In [23]: set(s)
Out[23]: {'a', 'b', 'c'}

In [24]: 'a' in set(s)
Out[24]: True

Come sottolineato da @DSM, potrebbe essere più efficiente (soprattutto se lo stai facendo solo per un valore) utilizzare direttamente sui valori:

In [31]: s.values
Out[31]: array(['a', 'b', 'c'], dtype=object)

In [32]: 'a' in s.values
Out[32]: True

2
Non voglio sapere se è necessariamente unico, principalmente voglio sapere se è lì.
Michael,

24
Penso che 'a' in s.valuesdovrebbe essere più veloce per le serie lunghe.
DSM,

4
@AndyHayden Sai perché, perché, Panda 'a' in ssceglie di controllare l'indice anziché i valori delle serie? Nei dizionari controllano le chiavi, ma una serie di panda dovrebbe comportarsi più come una lista o un array, no?
Lei,

3
A partire da Panda 0.24.0, utilizzando s.valuesed df.valuesè altamente sconsigliato. Vedere questo . Inoltre, in s.valuesrealtà è molto più lento in alcuni casi.
Qusai Alothman,

1
@QusaiAlothman né .to_numpyoppure .arraysono disponibili su una serie, quindi non sono del tutto sicuro di quale alternativa che stanno sostenendo (Io non leggo "altamente sconsigliato"). In realtà stanno dicendo che .values ​​potrebbe non restituire un array intorpidito, ad esempio nel caso di un categorico ... ma va bene come infunzionerà ancora come previsto (anzi più efficacemente che è controparte di array intorpidito)
Andy Hayden

27

Puoi anche usare pandas.Series.isin anche se è un po 'più lungo di 'a' in s.values:

In [2]: s = pd.Series(list('abc'))

In [3]: s
Out[3]: 
0    a
1    b
2    c
dtype: object

In [3]: s.isin(['a'])
Out[3]: 
0    True
1    False
2    False
dtype: bool

In [4]: s[s.isin(['a'])].empty
Out[4]: False

In [5]: s[s.isin(['z'])].empty
Out[5]: True

Ma questo approccio può essere più flessibile se devi abbinare più valori contemporaneamente per un DataFrame (vedi DataFrame.isin )

>>> df = DataFrame({'A': [1, 2, 3], 'B': [1, 4, 7]})
>>> df.isin({'A': [1, 3], 'B': [4, 7, 12]})
       A      B
0   True  False  # Note that B didn't match 1 here.
1  False   True
2   True   True

1
È inoltre possibile utilizzare la funzione DataFrame.any () :s.isin(['a']).any()
thando

17
found = df[df['Column'].str.contains('Text_to_search')]
print(found.count())

la found.count()volontà contiene il numero di partite

E se è 0, significa che la stringa non è stata trovata nella colonna.


2
ha funzionato per me, ma ho usato len (trovato) per ottenere il conteggio
kztd

1
Sì, Len (trovato) è un'opzione leggermente migliore.
Shahir Ansari

1
Questo approccio ha funzionato per me, ma ho dovuto includere i parametri na=Falsee il regex=Falsemio caso d'uso, come spiegato qui: pandas.pydata.org/pandas-docs/stable/reference/api/…
Mabyn

1
Ma string.contains esegue una ricerca di sottostringa. Es: se è presente un valore chiamato "head_hunter". Passare "testa" in str.contains partite e dà True che è sbagliato.
karthikeyan,

@karthikeyan Non è sbagliato. Dipende dal contesto della tua ricerca. Cosa succede se si cercano indirizzi o prodotti. Avrai bisogno di tutti i prodotti adatti alla descrizione.
Shahir Ansari,

6

Ho fatto alcuni semplici test:

In [10]: x = pd.Series(range(1000000))

In [13]: timeit 999999 in x.values
567 µs ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [15]: timeit x.isin([999999]).any()
9.54 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [16]: timeit (x == 999999).any()
6.86 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [17]: timeit 999999 in set(x)
79.8 ms ± 1.98 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: timeit x.eq(999999).any()
7.03 ms ± 33.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [22]: timeit x.eq(9).any()
7.04 ms ± 60 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

È interessante notare che non importa se cerchi 9 o 999999, sembra che impieghi la stessa quantità di tempo usando la sintassi in (deve usare la ricerca binaria)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [25]: timeit 9999 in x.values
647 µs ± 5.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [26]: timeit 999999 in x.values
642 µs ± 2.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [27]: timeit 99199 in x.values
644 µs ± 5.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [28]: timeit 1 in x.values
667 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Sembra che usare x.values ​​sia il più veloce, ma forse c'è un modo più elegante in panda?


Sarebbe bello se cambiassi l'ordine dei risultati dal più piccolo al più grande. Bel lavoro!
smm

4

Oppure usa Series.tolisto Series.any:

>>> s = pd.Series(list('abc'))
>>> s
0    a
1    b
2    c
dtype: object
>>> 'a' in s.tolist()
True
>>> (s=='a').any()
True

Series.tolistfa un elenco di a Series, e l'altro sto solo ricevendo un booleano Seriesda un normale Series, quindi controllando se ci sono Trues nel booleano Series.


1

Condizioni semplici:

if any(str(elem) in ['a','b'] for elem in df['column'].tolist()):

1

Uso

df[df['id']==x].index.tolist()

Se xè presente id, restituirà l'elenco degli indici in cui è presente, altrimenti fornisce un elenco vuoto.



0

Supponiamo che il tuo frame di dati sia simile a:

inserisci qui la descrizione dell'immagine

Ora si desidera verificare se il nome file "80900026941984" è presente nel frame di dati o meno.

Puoi semplicemente scrivere:

if sum(df["filename"].astype("str").str.contains("80900026941984")) > 0:
    print("found")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.