Как фильтровать строки в pandas с помощью регулярных выражений

Я хотел бы чисто фильтровать фрейм с использованием регулярного выражения в одном из столбцов.

Для надуманного примера:

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

Это заставляет меня искусственно помещать группу в регулярное выражение, но, похоже, может быть, это не простой способ. Есть ли лучший способ сделать это?

Ответ 1

Используйте вместо этого содержит:

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

Ответ 2

Поиск нескольких столбцов с помощью dataframe:

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

Ответ 3

Это может быть немного поздно, но теперь это легче сделать в Пандах. Вы можете вызвать соответствие с as_indexer=True чтобы получить логические результаты. Это подтверждается (вместе с различием между match и contains) здесь.

Ответ 4

Уже есть функция обработки строк 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 и т.д.

Ответ 5

Спасибо за отличный ответ @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)]

Ответ 6

Напишите булеву функцию, которая проверяет регулярное выражение и используйте команду apply в столбце.

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

Ответ 7

Использование str ломтик

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat