কীভাবে রেজেক্স দ্বারা পান্ডাসে সারিগুলি ফিল্টার করা যায়


169

আমি কলামগুলির মধ্যে একটিতে রেজেক্স ব্যবহার করে একটি ডেটাফ্রেম পরিষ্কারভাবে ফিল্টার করতে চাই।

স্বীকৃত উদাহরণের জন্য:

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
আপনি যদি রেজিজেসগুলিতে বিবাহিত না হন তবে foo[foo.b.str.startswith("f")]কাজ করবে।
ডিএসএম

আইএমএইচওও আমি মনে করি foo[foo.b.str.match('(f.*)').str.len() > 0]এটি যথেষ্ট ভাল সমাধান! শুরুর চেয়ে আরও কাস্টমাইজযোগ্য এবং দরকারী কারণ এটি এতে রেজেসের বহুমুখিতা প্যাক করে।
গণ্ডগোল_রোস্টার

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'? দেখে মনে হচ্ছে আপনি আলাদা প্রশ্নের উত্তর দিচ্ছেন।
গণ্ডগোল_রোস্টার

ফ্রেম df হয়। এটি একই প্রশ্নের সাথে সম্পর্কিত তবে এটি কীভাবে এক লাইনের কোডে একাধিক কলাম ('ফাইলের নাম' এবং 'ফাইল_পাথ') ফিল্টার করতে পারে তার উত্তর দেয়।
লক্ষ্মণ সেনাথিরজাহ

12

এটি কিছুটা দেরিতে হতে পারে তবে পান্ডসে এটি করা এখন আরও সহজ। as_indexer=Trueবুলিয়ান ফলাফল পেতে আপনি এর সাথে ম্যাচ কল করতে পারেন । এই নথিভুক্ত করা হয় (মধ্যে পার্থক্য সহ matchএবং contains) এখানে


11

@ User3136169 দুর্দান্ত উত্তরের জন্য ধন্যবাদ, কী কীভাবে এটিও করা যাবে না এর একটি উদাহরণ যা ননটাইপ মানগুলি অপসারণ করে removing

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)]

এছাড়াও আপনি একটি আর্গ হিসাবে regex যোগ করতে পারেন:

def regex_filter(val,myregex):
    ...

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

1
ধন্যবাদ, এর কারণে আমি নির্বিচারে ভবিষ্যদ্বাণী করে একটি কলাম ফিল্টার করার উপায় খুঁজে পেয়েছি।
jman

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.