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


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.