如何通过正则表达式过滤pandas中的行

jus*_*nvf 144 python regex 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
Run Code Online (Sandbox Code Playgroud)

我想将行过滤为f使用正则表达式开头的行.先去:

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

这不是太有用了.但是这会得到我的布尔索引:

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

所以我可以通过以下方式来限制:

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

这让我人为地把一组人放进了正则表达式,看起来可能不是那种干净的方式.有一个更好的方法吗?

wai*_*kuo 161

使用包含而不是:

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

  • 如何将布尔值反转?找到它:http://stackoverflow.com/questions/15998188/how-can-i-obtain-the-element-wise-logical-not-of-a-pandas-series (10认同)
  • 是否有可能只获得那些具有True的行? (4认同)
  • @shockwave 你应该使用:```df.loc[df.b.str.contains('^f'), :]``` (4认同)
  • @shockwave 你也可以只使用 `df[df.b.str.contains('^f'), :]` (3认同)

小智 16

使用dataframe进行多列搜索:

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

  • `框架`?和`'C:\test\test.txt'`?好像你在回答一个不同的问题。 (2认同)

Erk*_*rin 15

已有字符串处理功能Series.str.startswith().

你应该试试foo[foo.b.str.startswith('f')].

结果:

    a   b
1   2   foo
2   3   fat
Run Code Online (Sandbox Code Playgroud)

我想你的期望.


小智 11

这可能有点晚了,但现在在熊猫中更容易做到.您可以调用match as_indexer=True来获取布尔结果.这是记录(与之间的差异沿matchcontains)在这里.


spa*_*row 8

感谢@ 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)]
Run Code Online (Sandbox Code Playgroud)


Mar*_*her 6

使用 Python 内置的编写 lambda 表达式的功能,我们可以通过任意正则表达式操作进行过滤,如下所示:

import re  

# with foo being our pd dataframe
foo[foo['b'].apply(lambda x: True if re.search('^f', x) else False)]
Run Code Online (Sandbox Code Playgroud)

通过使用 re.search,您可以通过复杂的正则表达式样式查询进行过滤,在我看来,这更强大。(因为str.contains相当有限)

另外值得一提的是:您希望字符串以小“f”开头。通过使用正则表达式,f.*您可以将 f 匹配到文本中的任意位置。通过使用该^符号,您明确声明您希望它位于内容的开头。所以使用^f可能是一个更好的主意:)


use*_*169 5

编写一个布尔函数来检查正则表达式并在列上使用apply

foo[foo['b'].apply(regex_function)]
Run Code Online (Sandbox Code Playgroud)