Cách lọc hàng trong gấu trúc bằng regex


169

Tôi muốn lọc sạch một khung dữ liệu bằng regex trên một trong các cột.

Đối với một ví dụ giả định:

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

Tôi muốn lọc các hàng cho những hàng bắt đầu fbằng regex. Đầu tiên đi

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

Điều đó không quá hữu ích. Tuy nhiên, điều này sẽ giúp tôi có được chỉ số boolean của mình:

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

Vì vậy, sau đó tôi có thể thực hiện hạn chế của mình bằng cách:

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

Điều đó làm cho tôi giả tạo đưa một nhóm vào regex, và dường như có thể không phải là con đường sạch sẽ để đi. Có cách nào tốt hơn để làm điều này?


5
Nếu bạn không kết hôn với regexes, foo[foo.b.str.startswith("f")]sẽ hoạt động.
DSM

IMHO tôi nghĩ foo[foo.b.str.match('(f.*)').str.len() > 0]là một giải pháp đủ tốt! Tùy biến và hữu ích hơn so với startwith vì nó chứa tính linh hoạt của regex trong đó.
tumultous_rooster

3
điều này có thể hơi muộn nhưng trong các phiên bản mới hơn của gấu trúc, vấn đề đã được khắc phục. dòng foo[foo.b.str.match('f.*')]hoạt động trong gấu trúc 0,24.2 cho tôi.
Behzad Mehrtash

Câu trả lời:


198

Sử dụng có chứa thay thế:

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

11
Làm thế nào các boolean có thể được đảo ngược? Đã tìm thấy: stackoverflow.com/questions/15998188/ từ
dmeu

4
Có thể chỉ nhận được những hàng có True?
sóng xung kích

2
@shockwave bạn nên sử dụng:df.loc[df.b.str.contains('^f'), :]
Rafa

1
@shockwave Ngoài ra, bạn chỉ có thể sử dụngdf[df.b.str.contains('^f'), :]
David Jung

23

Đã có một chức năng xử lý chuỗi Series.str.startswith(). Bạn nên thử foo[foo.b.str.startswith('f')].

Kết quả:

    a   b
1   2   foo
2   3   fat

Tôi nghĩ những gì bạn mong đợi.

Ngoài ra, bạn có thể sử dụng chứa với tùy chọn regex. Ví dụ:

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

Kết quả:

    a   b
1   2   foo

na=False là để ngăn lỗi trong trường hợp có các giá trị nan, null, v.v.


Tôi đã sửa đổi điều này và nó đã làm việc cho tôidf[~df.CITY.str.contains('~.*', regex= True, na=False)]
Patty Jula

Cảm ơn bạn! đây là một giải pháp tuyệt vời
Kedar Joshi

20

Tìm kiếm nhiều cột với dataframe:

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

2
frame? và 'C:\test\test.txt'? Có vẻ như bạn đang trả lời một câu hỏi khác.
tumultous_rooster

khung là df. liên quan đến cùng một câu hỏi, nhưng nó trả lời cách lọc nhiều cột ('tên tệp' và 'file_path') trong một mã dòng.
lakshman senathirajah

12

Điều này có thể hơi muộn, nhưng điều này bây giờ dễ thực hiện hơn ở Pandas. Bạn có thể gọi kết hợp với as_indexer=Trueđể có kết quả boolean. Điều này được ghi lại (cùng với sự khác biệt giữa matchcontains) ở đây .


11

Cảm ơn câu trả lời tuyệt vời @ user3136169, đây là một ví dụ về cách thực hiện điều đó cũng có thể loại bỏ các giá trị 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)]

Ngoài ra, bạn cũng có thể thêm regex dưới dạng arg:

def regex_filter(val,myregex):
    ...

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

1
cảm ơn, vì điều này tôi đã tìm ra một cách để lọc một cột theo vị ngữ tùy ý.
jman

9

Viết hàm Boolean kiểm tra biểu thức chính quy và sử dụng áp dụng trên cột

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

1

Sử dụng str lát

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.