Як фільтрувати рядки в пандах за допомогою регулярного вираження


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")]буде працювати.
DSM

IMHO Я думаю foo[foo.b.str.match('(f.*)').str.len() > 0], що це досить хороше рішення! Більш настроюваний і корисний, ніж startwith, тому що він пакує універсальність регулярного вираження в ньому.
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 / ...
ДМЕЙ

4
Чи можливо отримати лише ті рядки, що мають True?
ударна хвиля

2
@shockwave ви повинні використовувати:df.loc[df.b.str.contains('^f'), :]
Рафа

1
@shockwave Також ви можете просто скористатисяdf[df.b.str.contains('^f'), :]
David Jung

24

Вже є функція обробки струн 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 полягає у запобіганні помилок у разі наявності nan, null тощо значень


Я змінив це, і це спрацювало на мене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

кадр df. пов'язане з тим самим питанням, але він відповідає на те, як відфільтрувати кілька стовпців ("ім'я файлу" та "файл_пат") в одному кодовому рядку.
lakshman senathirajah

12

Це може бути трохи пізно, але це зараз простіше зробити в Pandas. Ви можете зателефонувати на матч, as_indexer=Trueщоб отримати булеві результати. Це задокументовано (разом із різницею між matchта contains) тут .


11

Дякуємо за чудову відповідь @ user3136169, ось приклад того, як це можна зробити, також видаляючи значення NoneType.

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

Також ви можете додати регулярний вираз як аргумент:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.