यदि एक स्ट्रिंग में एक सूची में पैंडिंग में एक स्ट्रिंग शामिल है, तो परीक्षण कैसे करें?


119

क्या कोई ऐसा कार्य है जो संयोजन के बराबर होगा df.isin()और df[col].str.contains()?

उदाहरण के लिए, मान लें कि मेरे पास श्रृंखला है s = pd.Series(['cat','hat','dog','fog','pet']), और मैं उन सभी स्थानों को खोजना चाहता हूं जिनमें sकोई भी हो ['og', 'at'], मैं सब कुछ प्राप्त करना चाहता हूं, लेकिन 'पालतू'।

मेरे पास एक समाधान है, लेकिन यह बहुत अयोग्य है:

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

क्या ऐसा करने के लिए इससे अच्छा तरीका है?


नोट : @unutbu द्वारा वर्णित एक समाधान है जो उपयोग करने से अधिक कुशल है pd.Series.str.contains। यदि प्रदर्शन एक मुद्दा है, तो यह जांच के लायक हो सकता है।
— jpp

बहुत से कीवर्ड / रीगेक्स का उपयोग करते हुए आंशिक स्ट्रिंग खोज के लिए इस उत्तर की जाँच करने की सलाह देते हैं (स्क्रॉल करें " मल्टीपल सब्जेक्टिंग सर्च " सबहेडिंग के लिए)।
— cs95

जवाबों:


219

एक विकल्प बस regex |चरित्र का उपयोग करने के लिए अपनी श्रृंखला में शब्दों में से प्रत्येक में s(अभी भी उपयोग करके str.contains) मिलान करने के लिए है ।

आप में शब्दों में शामिल होने से regex निर्माण कर सकते हैं 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/… भी। पांडा ०.१५ से शुरू, स्ट्रिंग ऑपरेशन और भी आसान हैं
— २१:१

6
एक बात जो आपको ध्यान रखनी है वह यह है कि यदि खोज में एक स्ट्रिंग में विशेष रेगेक्स वर्ण हैं (आप re.escape के साथ मैप कर सकते हैं )।
— एंडी हेडन

@AndyHayden धन्यवाद, मैंने इस जटिलता को ध्यान में रखते हुए अपने उत्तर में सुधार किया है।
— एलेक्स रिले

मुझे नहीं पता कि आपका तरीका "str.startswith ('|' .join (खोज)) के साथ काम क्यों नहीं करता है"
— डू ह्यून शिन

48

आप str.containsअकेले regex पैटर्न का उपयोग करके उपयोग कर सकते हैं 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 

इसे कैसे करें?
— जैकोसोलारी

1
@JacoSolari इस उत्तर को देखें stackoverflow.com/questions/37011734/…
— जेम्स

1
@ जेम्स हां, धन्यवाद। यहाँ पूरा करने के लिए उस उत्तर में सबसे अधिक उत्थान किया गया है। df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)
— जैकोसोलरी

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

लैम्ब्डा लागू करें:

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.