Cara memfilter baris dalam panda dengan regex


169

Saya ingin memfilter dataframe menggunakan regex pada salah satu kolom.

Untuk contoh yang dibuat-buat:

In [210]: foo = pd.DataFrame({'a' : [1,2,3,4], 'b' : ['hi', 'foo', 'fat', 'cat']})
In [211]: foo
Out[211]: 
   a    b
0  1   hi
1  2  foo
2  3  fat
3  4  cat

Saya ingin memfilter baris ke yang dimulai dengan fmenggunakan regex. Go pertama:

In [213]: foo.b.str.match('f.*')
Out[213]: 
0    []
1    ()
2    ()
3    []

Itu tidak terlalu berguna. Namun ini akan membuat saya indeks boolean saya:

In [226]: foo.b.str.match('(f.*)').str.len() > 0
Out[226]: 
0    False
1     True
2     True
3    False
Name: b

Jadi saya bisa melakukan pembatasan dengan:

In [229]: foo[foo.b.str.match('(f.*)').str.len() > 0]
Out[229]: 
   a    b
1  2  foo
2  3  fat

Itu membuat saya secara artifisial menempatkan grup ke dalam regex, dan sepertinya mungkin bukan cara yang bersih untuk pergi. Apakah ada cara yang lebih baik untuk melakukan ini?


5
Jika Anda tidak terikat dengan regex, foo[foo.b.str.startswith("f")]akan berhasil.
DSM

IMHO saya pikir foo[foo.b.str.match('(f.*)').str.len() > 0]adalah solusi yang cukup bagus! Lebih dapat dikustomisasi dan bermanfaat daripada mulai dengan karena ini mengemas fleksibilitas regex di dalamnya.
tumultous_rooster

3
ini mungkin agak terlambat tetapi dalam versi panda yang lebih baru, masalahnya sudah diperbaiki. baris foo[foo.b.str.match('f.*')]bekerja di panda 0.24.2 untuk saya.
Behzad Mehrtash

Jawaban:


198

Gunakan mengandung sebagai gantinya:

In [10]: df.b.str.contains('^f')
Out[10]: 
0    False
1     True
2     True
3    False
Name: b, dtype: bool

11
Bagaimana bisa boolean dibalik? Ditemukan: stackoverflow.com/questions/15998188/…
dmeu

4
Apakah mungkin untuk mendapatkan hanya baris-baris yang memiliki True?
shockwave

2
@shockwave, Anda harus menggunakan:df.loc[df.b.str.contains('^f'), :]
Rafa

1
@shockwave Anda juga bisa menggunakandf[df.b.str.contains('^f'), :]
David Jung

23

Sudah ada fungsi penanganan string Series.str.startswith(). Kamu harus mencobanyafoo[foo.b.str.startswith('f')] .

Hasil:

    a   b
1   2   foo
2   3   fat

Saya pikir apa yang Anda harapkan.

Atau Anda dapat menggunakan berisi dengan opsi regex. Sebagai contoh:

foo[foo.b.str.contains('oo', regex= True, na=False)]

Hasil:

    a   b
1   2   foo

na=False adalah untuk mencegah Kesalahan jika ada nilai nan, null dll


Saya memodifikasi ini dan itu berhasil untuk sayadf[~df.CITY.str.contains('~.*', regex= True, na=False)]
Patty Jula

Terima kasih! ini adalah solusi hebat
Kedar Joshi

20

Pencarian beberapa kolom dengan bingkai data:

frame[frame.filename.str.match('*.'+MetaData+'.*') & frame.file_path.str.match('C:\test\test.txt')]

2
frame? dan 'C:\test\test.txt'? Sepertinya Anda menjawab pertanyaan yang berbeda.
tumultous_rooster

frame adalah df. ini terkait dengan pertanyaan yang sama, tetapi menjawab bagaimana memfilter banyak kolom ('nama file' dan 'file_path') dalam satu kode baris.
lakshman senathirajah

12

Ini mungkin agak terlambat, tetapi ini sekarang lebih mudah dilakukan di Panda. Anda dapat memanggil pertandingan dengan as_indexer=Trueuntuk mendapatkan hasil boolean. Ini didokumentasikan (bersama dengan perbedaan antara matchdan contains) di sini .


11

Terima kasih atas jawaban yang bagus @ user3136169, berikut adalah contoh bagaimana hal itu dapat dilakukan juga dengan menghapus nilai NoneType.

def regex_filter(val):
    if val:
        mo = re.search(regex,val)
        if mo:
            return True
        else:
            return False
    else:
        return False

df_filtered = df[df['col'].apply(regex_filter)]

Anda juga dapat menambahkan regex sebagai argumen:

def regex_filter(val,myregex):
    ...

df_filtered = df[df['col'].apply(res_regex_filter,regex=myregex)]

1
terima kasih, karena ini saya menemukan cara untuk menyaring kolom dengan predikat sewenang-wenang.
jman

9

Tulis fungsi Boolean yang memeriksa regex dan gunakan terapkan pada kolom

foo[foo['b'].apply(regex_function)]

1

Menggunakan str irisan

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.