Pandas数据框使用正则表达式检查值是否存在

10

我有一个大的数据框,我想检查是否有任何单元格包含 admin 字符串。

   col1                   col2 ... coln
0   323           roster_admin ... rota_user
1   542  assignment_rule_admin ... application_admin
2   123           contact_user ... configuration_manager
3   235         admin_incident ... incident_user
... ...  ...                   ... ...

我尝试使用df.isin(['*admin*']).any(),但看起来isin不支持正则表达式。如何使用正则表达式搜索所有列?

由于数据框包含超过1000万行和许多列,并且效率对我很重要,因此我避免使用循环。


将正则表达式应用于Pandas数据框架的方法 - Siddharth
df.isin(vals) 检查 DataFrame/Series 的值是否 vals 中。这里的 vals 必须是集合或类列表。我认为 df.isin(vals) 不是检查 DataFrame 列中是否包含 vals 的自然方式。 - YaOzI
2个回答

14

有两个解决方案:

  1. df.col.apply 方法更直接但稍微慢一些:

In [1]: import pandas as pd

In [2]: import re

In [3]: df = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':['admin', 'aa', 'bb', 'c_admin_d', 'ee_admin']})

In [4]: df
Out[4]: 
   col1       col2
0     1      admin
1     2         aa
2     3         bb
3     4  c_admin_d
4     5   ee_admin

In [5]: r = re.compile(r'.*(admin).*')

In [6]: df.col2.apply(lambda x: bool(r.match(x)))
Out[6]: 
0     True
1    False
2    False
3     True
4     True
Name: col2, dtype: bool

In [7]: %timeit -n 100000 df.col2.apply(lambda x: bool(r.match(x)))
167 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

  1. np.vectorize 方法需要 import numpy,但是它更高效(在我的 timeit 测试中快了约4倍)。

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: import re

In [4]: df = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':['admin', 'aa', 'bb', 'c_admin_d', 'ee_admin']})

In [5]: df
Out[5]: 
   col1       col2
0     1      admin
1     2         aa
2     3         bb
3     4  c_admin_d
4     5   ee_admin

In [6]: r = re.compile(r'.*(admin).*')

In [7]: regmatch = np.vectorize(lambda x: bool(r.match(x)))

In [8]: regmatch(df.col2.values)
Out[8]: array([ True, False, False,  True,  True])

In [9]: %timeit -n 100000 regmatch(df.col2.values)
43.4 µs ± 362 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

由于您更改了问题以检查任何单元格,并且还关注时间效率:

# if you want to check all columns no mater what `dtypes` they are
dfs = df.astype(str, copy=True, errors='raise')
regmatch(dfs.values) # This will return a 2-d array of booleans
regmatch(dfs.values).any() # For existence.

你仍然可以使用df.applymap方法,但是它会更慢。

dfs = df.astype(str, copy=True, errors='raise')
r = re.compile(r'.*(admin).*')
dfs.applymap(lambda x: bool(r.match(x))) # This will return a dataframe of booleans.
dfs.applymap(lambda x: bool(r.match(x))).any().any() # For existence.

如果一列的值是一个列表,例如 'col2':[['aa','admin'],['admin_b']..],该怎么办? - elisa

7

试试这个:

import pandas as pd

df=pd.DataFrame(
    {'col1': [323,542,123,235],
     'col2': ['roster_admin','assignment_rule_admin','contact_user','admin_incident'] ,
    })

df.apply(lambda row: row.astype(str).str.contains('admin').any(), axis=1)

输出:

0     True
1     True
2    False
3     True
dtype: bool

@MichaelDz 我们只需要检查第二列中的单词“admin”吗? - min2bro
抱歉,我在原帖中没有提到我想要搜索所有列。 - Michael Dz
@MichaelDz 甚至检查 col1?它只包含数字并且具有 dtypeint64 吗?或者您有一个包含混合数据类型的列的数据框? - YaOzI
我有混合数据。 - Michael Dz
@MichaelDz 你用正则表达式和 isin 结合了吗?我还没有找到这样做的方法。 - user137717
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接