Làm cách nào để kiểm tra xem một chuỗi có chứa một trong các chuỗi con trong danh sách, bằng gấu trúc không?


119

Có chức năng nào tương đương với sự kết hợp của df.isin()df[col].str.contains()không?

Ví dụ: giả sử tôi có bộ truyện s = pd.Series(['cat','hat','dog','fog','pet'])và tôi muốn tìm tất cả những nơi scó bất kỳ bộ sách nào trong số đó ['og', 'at'], tôi muốn lấy mọi thứ trừ 'thú cưng'.

Tôi có một giải pháp, nhưng nó không phù hợp:

searchfor = ['og', 'at']
found = [s.str.contains(x) for x in searchfor]
result = pd.DataFrame[found]
result.any()

Có cách nào tốt hơn để làm điều này?


Lưu ý : Có một giải pháp được mô tả bởi @unutbu hiệu quả hơn là sử dụng pd.Series.str.contains. Nếu hiệu suất là một vấn đề, thì điều này có thể đáng để điều tra.
jpp

Thực sự khuyên bạn nên xem câu trả lời này cho tìm kiếm một phần chuỗi sử dụng nhiều từ khóa / regex (cuộn xuống tiêu đề phụ " Tìm kiếm nhiều chuỗi con ").
cs95

Câu trả lời:


219

Một tùy chọn chỉ là sử dụng |ký tự regex để cố gắng khớp từng chuỗi con trong các từ trong Chuỗi của bạn s(vẫn đang sử dụng str.contains).

Bạn có thể xây dựng regex bằng cách nối các từ searchforvới |:

>>> searchfor = ['og', 'at']
>>> s[s.str.contains('|'.join(searchfor))]
0    cat
1    hat
2    dog
3    fog
dtype: object

Như @AndyHayden lưu ý trong các ý kiến dưới đây, chăm sóc nếu chuỗi con của bạn có ký tự đặc biệt như $^mà bạn muốn kết hợp theo nghĩa đen. Các ký tự này có ý nghĩa cụ thể trong ngữ cảnh của cụm từ thông dụng và sẽ ảnh hưởng đến việc đối sánh.

Bạn có thể làm cho danh sách các chuỗi con của mình an toàn hơn bằng cách thoát các ký tự không phải chữ và số bằng re.escape:

>>> import re
>>> matches = ['$money', 'x^y']
>>> safe_matches = [re.escape(m) for m in matches]
>>> safe_matches
['\\$money', 'x\\^y']

Các chuỗi có trong danh sách mới này sẽ khớp với từng ký tự khi được sử dụng với str.contains.


4
có thể tốt để thêm liên kết này pandas.pydata.org/pandas-docs/stable/… . Bắt đầu từ gấu trúc 0,15, các hoạt động chuỗi thậm chí còn dễ dàng hơn
goofd

6
một điều bạn phải quan tâm là nếu một chuỗi trong searchfor có các ký tự regex đặc biệt (bạn có thể ánh xạ bằng re.escape ).
Andy Hayden

@AndyHayden Cảm ơn bạn, tôi đã cải thiện câu trả lời của mình để tính đến sự phức tạp này.
Alex Riley,

Tôi không biết lý do tại sao phương pháp của bạn không làm việc với "str.startswith ( '|' .join (searchfor))"
Doo Hyun Shin

48

Bạn có thể sử dụng str.containsmột mình với mẫu regex bằng cách sử dụng OR (|):

s[s.str.contains('og|at')]

Hoặc bạn có thể thêm chuỗi vào dataframesau đó sử dụng str.contains:

df = pd.DataFrame(s)
df[s.str.contains('og|at')] 

Đầu ra:

0 cat
1 hat
2 dog
3 fog 

làm thế nào để làm điều đó cho AND?
JacoSolari

1
@JacoSolari xem câu trả lời này stackoverflow.com/questions/37011734/…
James

1
@James vâng, cảm ơn. Để hoàn thành, đây là câu trả lời được ủng hộ nhiều nhất trong câu trả lời đó. df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)
JacoSolari

1

Đây là một lambda một dòng cũng hoạt động:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)

Đầu vào:

searchfor = ['og', 'at']

df = pd.DataFrame([('cat', 1000.0), ('hat', 2000000.0), ('dog', 1000.0), ('fog', 330000.0),('pet', 330000.0)], columns=['col1', 'col2'])

   col1  col2
0   cat 1000.0
1   hat 2000000.0
2   dog 1000.0
3   fog 330000.0
4   pet 330000.0

Áp dụng Lambda:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)

Đầu ra:

    col1    col2        TrueFalse
0   cat     1000.0      1
1   hat     2000000.0   1
2   dog     1000.0      1
3   fog     330000.0    1
4   pet     330000.0    0
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.