pandas에서 문자열에 목록의 하위 문자열 중 하나가 포함되어 있는지 테스트하는 방법은 무엇입니까?


119

df.isin()및 의 조합에 해당하는 기능이 df[col].str.contains()있습니까?

예를 들어, I has the series s = pd.Series(['cat','hat','dog','fog','pet']), I have to find all places where sof any of ['og', 'at'], I would want to get all than the 'pet'.

나는 해결책이 있지만 다소 우아하지 않습니다.

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

이 작업을 수행하는 더 좋은 방법이 있습니까?


참고 :를 사용하는 것보다 더 효율적인 @unutbu에 의해 설명 된 솔루션이 있습니다 pd.Series.str.contains. 성능이 문제인 경우 조사해 볼 가치가 있습니다.
jpp

여러 키워드 / 정규식을 사용하는 부분 문자열 검색에 대해이 답변 을 확인하는 것이 좋습니다 ( " Multiple Substring Search "부제목으로 스크롤 ).
cs95

답변:


219

한 가지 옵션은 정규식 |문자 를 사용 하여 시리즈의 단어에있는 각 하위 문자열을 일치시키는 것입니다 s(여전히 사용 str.contains).

다음 searchfor과 같이 단어를 결합하여 정규식을 구성 할 수 있습니다 |.

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

@AndyHayden 아래 코멘트에 언급 한 바와 같이 귀하의 문자열과 같은 특수 문자가있는 경우, 알아서 $하고 ^말 그대로 일치합니다. 이러한 문자는 정규식 컨텍스트에서 특정 의미를 가지며 일치에 영향을줍니다.

다음을 사용하여 영숫자가 아닌 문자를 이스케이프하여 하위 문자열 목록을 더 안전하게 만들 수 있습니다 re.escape.

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

이 새 목록에있는 문자열은와 함께 사용할 때 문자 그대로 각 문자와 일치합니다 str.contains.


4
이 링크 pandas.pydata.org/pandas-docs/stable/… 도 추가하는 것이 좋습니다 . pandas 0.15부터 문자열 연산이 훨씬 더 쉬워
졌습니다

6
주의해야 할 한 가지는 searchfor의 문자열에 특수 정규식 문자가 있는지 여부 입니다 (re.escape로 매핑 할 수 있음 ).
Andy Hayden

@AndyHayden 감사합니다.이 문제를 고려하여 답변을 개선했습니다.
Alex Riley

| 당신의 방법 "(.join (searchfor) '') str.startswith"로 일을하지 않는 이유를 모르겠어요
두 현 신

48

다음을 사용 str.contains하여 정규식 패턴과 함께 단독으로 사용할 수 있습니다 OR (|).

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

또는 dataframe다음을 사용 하여 시리즈를 추가 할 수 있습니다 str.contains.

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

산출:

0 cat
1 hat
2 dog
3 fog 

AND를 위해 어떻게할까요?
JacoSolari

1
@JacoSolari이 답변을 확인하십시오. stackoverflow.com/questions/37011734/…
James

1
@James 예, 감사합니다. 완성을 위해 여기에 그 답변에서 가장 많이 찬성 된 oneliner가 있습니다. df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)
JacoSolari

1

다음은 또한 작동하는 한 줄 람다입니다.

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

입력:

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

Lambda 적용 :

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

산출:

    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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.