Python 如何按正则表达式筛选pandas中的行

Python 如何按正则表达式筛选pandas中的行,python,regex,pandas,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 我想使用正则表达式将行筛选为以f开头的行。第一步: In [213]: foo.b.str.match('f.*'

我想在其中一列上使用正则表达式干净地过滤数据帧

举一个人为的例子:

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
这让我人为地把一组人加入正则表达式,似乎这不是一个干净的方法。有更好的方法吗?

改用:


使用dataframe进行多列搜索:

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

可能有点晚了,但现在打电话给熊猫更容易做到这一点。解释
match
fullmatch
之间的差异包含


请注意,为了使用结果进行索引,请设置
na=False
参数(或者
True
如果希望在结果中包含nan)。

已经有一个字符串处理函数
Series.str.startswith()
。 您应该尝试
foo[foo.b.str.startswith('f')]

结果:

    a   b
1   2   foo
2   3   fat
    a   b
1   2   foo
我想你期望的是什么

或者,您可以将contains与regex一起使用。例如:

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

    a   b
1   2   foo
2   3   fat
    a   b
1   2   foo

na=False
是为了防止出现nan、null等错误。值

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

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

感谢@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)]
您还可以将正则表达式添加为参数:

def regex_filter(val,myregex):
    ...

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

使用
str
slice

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

如果你没有拘泥于正则表达式,
foo[foo.b.str.startswith(“f”)]
会起作用。我认为
foo[foo.b.str.match('(f.*)).str.len()>0]
是一个非常好的解决方案!比startswith更具可定制性和实用性,因为它包含了正则表达式的多功能性。这可能有点晚,但在新版本的pandas中,问题已经解决。行
foo[foo.b.str.match('f.*')]
在pandas 0.24.2中对我有效。布尔值如何反转?找到它:是否可以只获取那些具有True的行?@shockwave您应该使用:
df.loc[df.b.str.contains(“^f”),:]
@shockwave您也可以只使用
df[df.b.str.contains(“^f”),:]
frame
?和
'C:\test\test.txt'
?看起来你在回答一个不同的问题。框架是df。它与同一个问题有关,但它回答了如何在一行代码中过滤多个列(“filename”和“file_path”)。谢谢,正因为如此,我找到了一种通过任意谓词过滤列的方法。我对此进行了修改,它为我工作
df[~df.CITY.str.contains(“~*”,regex=True,na=False)]
谢谢!这是一个很好的解决方案