Pandalar'daki satırları regex ile filtreleme


169

Ben temiz sütunlardan birinde regex kullanarak bir veri çerçevesi filtre istiyorum.

Çağdaş bir örnek için:

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

fBir regex kullanarak başlayanlara satırları filtrelemek istiyorum . Ilk önce git:

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

Bu çok kullanışlı değil. Ancak bu beni boole dizinimi alacak:

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

Böylece kısıtlamamı şu şekilde yapabilirim:

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

Bu bana yapay olarak bir grubu normal ifadeye koymamı sağlıyor ve belki de temiz bir yol gibi görünmüyor. Bunu yapmanın daha iyi bir yolu var mı?


5
Normal ifadelere bağlı değilseniz foo[foo.b.str.startswith("f")], işe yarayacaktır.
DSM

IMHO Bence foo[foo.b.str.match('(f.*)').str.len() > 0]yeterince iyi bir çözüm! Regex'in çok yönlülüğünü paketlediği için başlangıçtan daha özelleştirilebilir ve kullanışlı.
tumultous_rooster

3
bu biraz geç olabilir, ancak pandaların yeni sürümlerinde sorun giderildi. hat foo[foo.b.str.match('f.*')]benim için pandalarda 0.24.2 çalışır.
Behzad Mehrtash

Yanıtlar:



24

Zaten bir dize işleme işlevi var Series.str.startswith(). Denemelisin foo[foo.b.str.startswith('f')].

Sonuç:

    a   b
1   2   foo
2   3   fat

Ne beklediğinizi düşünüyorum.

Alternatif olarak içerir içeren regex seçeneğini kullanabilirsiniz. Örneğin:

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

Sonuç:

    a   b
1   2   foo

na=False nan, null vb. değerler olması durumunda Hataları önlemektir.


Bunu değiştirdim ve benim için çalıştıdf[~df.CITY.str.contains('~.*', regex= True, na=False)]
Patty Jula

Teşekkür ederim! Bu harika bir çözüm
Kedar Joshi

20

Veri çerçevesi ile birden çok sütun araması:

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

2
frame? ve 'C:\test\test.txt'? Farklı bir soruya cevap veriyorsun.
tumultous_rooster

çerçeve df'dir. aynı soru ile ilgilidir, ancak bir satır kodunda birden çok sütunun ('dosya adı' ve 'dosya_yolu') nasıl filtreleneceğini yanıtlar.
lakshman senathirajah

12

Bu biraz geç olabilir, ama şimdi Pandalarda bunu yapmak daha kolay. as_indexer=TrueBoole sonuçları almak için ile eşleşmeyi arayabilirsiniz . Bu (farkı arasındaki birlikte belgelenen matchve contains) burada .


11

@ User3136169 adlı harika yanıt için teşekkürler, bunun nasıl yapılacağına dair bir örnek NoneType değerlerinin kaldırılması.

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

Ayrıca argüman olarak argüman da ekleyebilirsiniz:

def regex_filter(val,myregex):
    ...

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

1
teşekkürler, bu nedenle bir sütü rastgele yüklemle filtrelemenin bir yolunu buldum.
jman

9

Normal ifadeyi kontrol eden bir Boole işlevi yazın ve sütuna uygula seçeneğini kullanın

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

1

str Dilim kullanma

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.