Bir dizenin pandalarda bir listedeki alt dizelerden birini içerip içermediğini nasıl test edebilirim?


119

df.isin()Ve kombinasyonuna eşdeğer olan herhangi bir işlev var mı df[col].str.contains()?

Örneğin, diziye sahip olduğumu s = pd.Series(['cat','hat','dog','fog','pet'])ve sherhangi birini içeren tüm yerleri bulmak istediğimi varsayalım , ['og', 'at']'evcil hayvan' dışında her şeyi almak isterim.

Bir çözümüm var, ama oldukça yetersiz:

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

Bunu yapmanın daha iyi bir yolu var mı?


Not : @unutbu tarafından tanımlanan kullanmaktan daha verimli bir çözüm var pd.Series.str.contains. Performans bir sorunsa, bu araştırmaya değer olabilir.
jpp

Birden çok anahtar kelime / normal ifade kullanarak kısmi dize araması için bu yanıta bakmanızı önemle tavsiye ederiz (" Çoklu Alt Dize Araması " alt başlığına gidin).
cs95

Yanıtlar:


219

Seçeneklerden |biri, Serinizdeki kelimelerdeki her bir alt dizeyi eşleştirmek için normal ifade karakterini kullanmaktır s(hala kullanılıyor str.contains).

Kelimeleri aşağıdakilerle birleştirerek normal ifadeyi searchforoluşturabilirsiniz |:

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

@AndyHayden aşağıda açıklamalarda belirtildiği gibi sizin altdizgelerin gibi özel karakterleri varsa, dikkat çekmek $ve ^kelimenin tam anlamıyla eşleştirmek istiyoruz. Bu karakterlerin normal ifadeler bağlamında belirli anlamları vardır ve eşleşmeyi etkiler.

Aşağıdakilerle alfasayısal olmayan karakterlerden kaçarak alt dizeler listenizi daha güvenli hale getirebilirsiniz re.escape:

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

Bu yeni listedeki dizeleri, birlikte kullanıldığında her karakterle tam anlamıyla eşleşecektir str.contains.


4
bu bağlantıyı pandas.pydata.org/pandas-docs/stable/… de eklemek iyi olabilir . Pandalar 0.15'ten başlayarak, dizi işlemleri daha da kolay
goofd

6
Dikkat etmeniz gereken bir şey , searchfor'daki bir dizenin özel normal ifade karakterlerine sahip olup olmadığıdır ( re.escape ile eşleyebilirsiniz ).
Andy Hayden

@AndyHayden Teşekkürler, bu komplikasyonu hesaba katmak için cevabımı geliştirdim.
Alex Riley

Metodunuzun neden "str.startswith ('|' .join (searchfor))" ile çalışmadığını bilmiyorum
Doo Hyun Shin

48

Şunları str.containskullanarak bir normal ifade kalıbıyla tek başına kullanabilirsiniz OR (|):

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

Veya seriyi a'ya ekleyebilir ve dataframeardından şunu kullanabilirsiniz str.contains:

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

Çıktı:

0 cat
1 hat
2 dog
3 fog 

AND için nasıl yapılır?
JacoSolari

1
@JacoSolari bu yanıtı kontrol edin stackoverflow.com/questions/37011734/…
James

1
@James evet, teşekkürler. Tamamlanması için buradaki cevapta en çok oy alan tek satır. df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)
JacoSolari

1

İşte aynı zamanda çalışan tek satırlık bir lambda:

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

Giriş:

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'yı uygulayın:

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

Çıktı:

    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
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.