रेगेक्स द्वारा पांडा में पंक्तियों को कैसे फ़िल्टर किया जाए


169

मैं कॉलम में से किसी एक पर regex का उपयोग करके डेटाफ़्रेम को साफ़ करना चाहूंगा।

एक आकस्मिक उदाहरण के लिए:

In [210]: foo = pd.DataFrame({'a' : [1,2,3,4], 'b' : ['hi', 'foo', 'fat', 'cat']})
In [211]: foo
Out[211]: 
   a    b
0  1   hi
1  2  foo
2  3  fat
3  4  cat

मैं उन पंक्तियों को फ़िल्टर करना चाहता हूं जो fएक रेगेक्स का उपयोग करके शुरू होती हैं । पहले जाओ:

In [213]: foo.b.str.match('f.*')
Out[213]: 
0    []
1    ()
2    ()
3    []

यह बहुत उपयोगी नहीं है। हालाँकि इससे मुझे मेरा बूलियन इंडेक्स मिलेगा:

In [226]: foo.b.str.match('(f.*)').str.len() > 0
Out[226]: 
0    False
1     True
2     True
3    False
Name: b

इसलिए मैं तब अपना प्रतिबंध लगा सकता था:

In [229]: foo[foo.b.str.match('(f.*)').str.len() > 0]
Out[229]: 
   a    b
1  2  foo
2  3  fat

हालांकि मुझे कृत्रिम रूप से एक समूह को रेगेक्स में डाल दिया गया है, और ऐसा लगता है कि शायद जाने के लिए स्वच्छ रास्ता नहीं है। क्या ऐसा करने के लिए इससे अच्छा तरीका है?


5
यदि आप regexes के लिए वचनबद्ध नहीं हैं, foo[foo.b.str.startswith("f")]तो काम करेंगे।
DSM

IMHO मुझे लगता foo[foo.b.str.match('(f.*)').str.len() > 0]है कि एक बहुत अच्छा समाधान है! शुरू से ही अधिक अनुकूलन और उपयोगी है क्योंकि यह इसमें रेगेक्स की बहुमुखी प्रतिभा को पैक करता है।
tumultous_rooster

3
यह थोड़ा देर हो सकता है लेकिन पांडा के नए संस्करणों में, समस्या तय हो गई है। लाइन foo[foo.b.str.match('f.*')]मेरे लिए 0.24.2 पांडा में काम करती है।
बेहजाद मेहरतश

जवाबों:


198

उपयोग होता है बजाय:

In [10]: df.b.str.contains('^f')
Out[10]: 
0    False
1     True
2     True
3    False
Name: b, dtype: bool

11
बूलियन को उलटा कैसे किया जा सकता है? यह पाया: stackoverflow.com/questions/15998188/…
dmeu

4
क्या केवल उन पंक्तियों को सच होना संभव है?
शॉकवेव

2
@ शॉकवेव आपको उपयोग करना चाहिए:df.loc[df.b.str.contains('^f'), :]
राफा

1
@ शॉकवेव भी आप बस इस्तेमाल कर सकते हैंdf[df.b.str.contains('^f'), :]
डेविड जंग

23

एक स्ट्रिंग हैंडलिंग फ़ंक्शन पहले से ही है Series.str.startswith()। आपको प्रयास करना चाहिए foo[foo.b.str.startswith('f')]

परिणाम:

    a   b
1   2   foo
2   3   fat

मुझे लगता है कि आप क्या उम्मीद करते हैं।

वैकल्पिक रूप से आप रेगेक्स विकल्प के साथ शामिल कर सकते हैं। उदाहरण के लिए:

foo[foo.b.str.contains('oo', regex= True, na=False)]

परिणाम:

    a   b
1   2   foo

na=False मामले में त्रुटियों को रोकने के लिए है वहाँ नैन, अशक्त आदि मान है


मैंने इसे संशोधित किया और इसने मेरे लिए काम कियाdf[~df.CITY.str.contains('~.*', regex= True, na=False)]
पैटी जुला

धन्यवाद! यह एक महान समाधान है
केदार जोशी

20

डेटाफ़्रेम के साथ एकाधिक कॉलम खोज:

frame[frame.filename.str.match('*.'+MetaData+'.*') & frame.file_path.str.match('C:\test\test.txt')]

2
frame? और 'C:\test\test.txt'? लगता है जैसे आप एक अलग सवाल का जवाब दे रहे हैं।
tumultous_rooster

फ्रेम डीएफ है। इसके एक ही सवाल से संबंधित है, लेकिन यह एक पंक्ति कोड में कई कॉलम ('फ़ाइलनाम' और 'file_path') को फ़िल्टर करने का जवाब देता है।
लक्ष्मण सेनतिराजह

12

यह थोड़ी देर हो सकती है, लेकिन अब पंडों में करना आसान है। आप as_indexer=Trueबुलियन परिणाम प्राप्त करने के लिए मैच के साथ कॉल कर सकते हैं । यह यहाँ ( matchऔर बीच के अंतर के साथ contains) प्रलेखित है


11

महान जवाब @ user3136169 के लिए धन्यवाद, यहां इस बात का एक उदाहरण है कि कैसे भी किया जा सकता है कोई भी नहीं है।

def regex_filter(val):
    if val:
        mo = re.search(regex,val)
        if mo:
            return True
        else:
            return False
    else:
        return False

df_filtered = df[df['col'].apply(regex_filter)]

इसके अलावा आप एक arg के रूप में regex भी जोड़ सकते हैं:

def regex_filter(val,myregex):
    ...

df_filtered = df[df['col'].apply(res_regex_filter,regex=myregex)]

1
धन्यवाद, इस वजह से मैंने मनमाने ढंग से विधेय द्वारा एक कॉलम को फ़िल्टर करने का एक तरीका निकाला।
जामन

9

एक बूलियन फ़ंक्शन लिखें जो रेगेक्स की जांच करता है और कॉलम पर लागू होता है

foo[foo['b'].apply(regex_function)]

1

str स्लाइस का उपयोग करना

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.