Cara menentukan apakah Kolom Pandas berisi nilai tertentu

156

Saya mencoba menentukan apakah ada entri di kolom Panda yang memiliki nilai tertentu. Saya mencoba melakukan ini dengan if x in df['id']. Saya pikir ini berhasil, kecuali ketika saya memberinya nilai yang saya tahu tidak ada di kolom 43 in df['id'], masih dikembalikan True. Ketika saya subset ke bingkai data hanya berisi entri yang cocok dengan id yang hilang df[df['id'] == 43], jelas, tidak ada entri di dalamnya. Bagaimana cara saya menentukan apakah kolom dalam bingkai data Pandas berisi nilai tertentu dan mengapa metode saya saat ini tidak berfungsi? (FYI, saya memiliki masalah yang sama ketika saya menggunakan implementasi dalam jawaban untuk pertanyaan serupa).

Michael
sumber

Jawaban:

183

in of a Series memeriksa apakah nilainya ada dalam indeks:

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

Salah satu opsi adalah untuk melihat apakah itu dalam nilai unik :

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

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

atau set python:

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

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

Seperti yang ditunjukkan oleh @DSM, mungkin lebih efisien (terutama jika Anda hanya melakukan ini untuk satu nilai) untuk digunakan langsung pada nilai-nilai:

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

In [32]: 'a' in s.values
Out[32]: True
Andy Hayden
sumber
2
Saya tidak ingin tahu apakah itu unik, terutama saya ingin tahu apakah itu ada di sana.
Michael
24
Saya pikir 'a' in s.valuesharus lebih cepat untuk Seri panjang.
DSM
4
@AndyHayden Tahukah Anda mengapa, karena 'a' in s, panda memilih untuk memeriksa indeks daripada nilai-nilai seri? Dalam kamus mereka memeriksa kunci, tetapi seri panda harus berperilaku lebih seperti daftar atau larik, bukan?
Lei
3
Mulai dari panda 0.24.0, menggunakan s.valuesdan df.valuessangat tidak disarankan. Lihat ini . Juga, s.valuessebenarnya jauh lebih lambat dalam beberapa kasus.
Qusai Alothman
1
@QusaiAlothman tidak .to_numpyatau .arraytidak tersedia pada Seri, jadi saya tidak sepenuhnya yakin alternatif apa yang mereka anjurkan (saya tidak membaca "sangat kecil hati"). Sebenarnya mereka mengatakan bahwa nilai. Mungkin tidak mengembalikan array numpy, misalnya dalam kasus kategori ... tapi itu baik karena inmasih akan bekerja seperti yang diharapkan (memang lebih efisien bahwa itu adalah array array numpy)
Andy Hayden
27

Anda juga dapat menggunakan panda.Series.isin meskipun sedikit lebih lama dari '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

Tetapi pendekatan ini bisa lebih fleksibel jika Anda harus mencocokkan beberapa nilai sekaligus untuk DataFrame (lihat 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
Pesta
sumber
Anda juga bisa menggunakan fungsi DataFrame.any () :s.isin(['a']).any()
thando
17
found = df[df['Column'].str.contains('Text_to_search')]
print(found.count())

surat found.count()wasiat berisi jumlah kecocokan

Dan jika 0 maka berarti string tidak ditemukan di Kolom.

Shahir Ansari
sumber
2
bekerja untuk saya, tetapi saya menggunakan len (ditemukan) untuk mendapatkan hitungan
kztd
1
Ya len (ditemukan) adalah opsi yang agak lebih baik.
Shahir Ansari
1
Pendekatan ini bekerja untuk saya tetapi saya harus memasukkan parameter na=Falsedan regex=Falseuntuk kasus penggunaan saya, seperti yang dijelaskan di sini: pandas.pydata.org/pandas-docs/stable/reference/api/…
Mabyn
1
Tapi string.contains melakukan pencarian substring. Mis: Jika ada nilai yang disebut "head_hunter". Melewati "head" di str.contains cocok dan memberikan True yang salah.
karthikeyan
@ karthikeyan Ini tidak salah. Tergantung pada konteks pencarian Anda. Bagaimana jika Anda mencari alamat atau produk. Anda akan membutuhkan semua produk yang sesuai dengan deskripsi.
Shahir Ansari
6

Saya melakukan beberapa tes sederhana:

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)

Menariknya tidak masalah jika Anda mencari 9 atau 999999, sepertinya butuh waktu yang sama menggunakan sintaks dalam (harus menggunakan pencarian biner)

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)

Sepertinya menggunakan nilai x. adalah yang tercepat, tapi mungkin ada cara yang lebih elegan di panda?

Allen Wang
sumber
Akan lebih bagus jika Anda mengubah urutan hasil dari terkecil ke terbesar. Kerja bagus!
smm
4

Atau gunakan Series.tolistatau 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.tolistmembuat daftar tentang a Series, dan yang lain saya hanya mendapatkan boolean Seriesdari reguler Series, lalu memeriksa apakah ada Trues di boolean Series.

U10-Maju
sumber
1

Kondisi sederhana:

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

Menggunakan

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

Jika xada idmaka akan mengembalikan daftar indeks di mana ia hadir, kalau tidak memberikan daftar kosong.

Ramana Sriwidya
sumber
1

Saya tidak menyarankan untuk menggunakan "value in series", yang dapat menyebabkan banyak kesalahan. Silakan lihat jawaban ini untuk detail: Menggunakan operator dalam seri Pandas

Vicky Ding
sumber
0

Misalkan Anda dataframe terlihat seperti:

masukkan deskripsi gambar di sini

Sekarang Anda ingin memeriksa apakah nama file "80900026941984" ada dalam kerangka data atau tidak.

Anda cukup menulis:

if sum(df["filename"].astype("str").str.contains("80900026941984")) > 0:
    print("found")
Namrata Tolani
sumber