Pandas Dataframe 使用正则表达式检查值是不是存在

Posted

技术标签:

【中文标题】Pandas Dataframe 使用正则表达式检查值是不是存在【英文标题】:Pandas Dataframe check if a value exists using regexPandas Dataframe 使用正则表达式检查值是否存在 【发布时间】:2018-12-12 17:21:39 【问题描述】:

我有一个大数据框,我想检查是否有任何单元格包含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 万行和许多列,效率对我来说很重要。

【问题讨论】:

检查***.com/questions/25292838/… df.isin(vals) 检查 DataFrame/Series 值是否vals。这里vals 必须设置或类似列表。我不认为 df.isin(vals) 是检查 vals 是否包含在 DataFrame 列中的自然方法。 【参考方案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)
    

    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']..]【参考方案2】:

试试这个:

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

【讨论】:

不幸的是,这个解决方案对我来说太慢了。我等了5分钟,最终放弃了。 isin 大约需要 5 秒。 @MichaelDz 我们只需要在 Col 2 中检查单词 admin 吗? 对不起,我在原帖中没有提到我要搜索所有列。 @MichaelDz 甚至检查col1?哪个只包含数字并且dtypeint64?或者你有一个数据框在列中包含混合数据类型? 我有一个混合数据。

以上是关于Pandas Dataframe 使用正则表达式检查值是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

Pandas - 过滤和正则表达式搜索 DataFrame 的索引

使用正则表达式解析多个文本字段并编译成 Pandas DataFrame

Pandas Dataframe 使用正则表达式检查值是不是存在

Pandas Dataframe - 根据正则表达式条件替换所有单元格值

pandas使用replace函数和正则表达式移除dataframe字符串数据列中尾部指定模式字符串(Removing trailing substring in dataframe)

pandas DataFrame过滤器正则表达式