优化 - 匹配dataframe列中的单词序列

时间:2017-10-03 13:39:50

标签: python regex pandas

我有一系列单词序列,我试图确定字符串列是否包含列表中的任何序列。如果有任何匹配,则新列应包含1,否则应为0 下面的代码实现了这一点,但是对于大数据它不能很好地扩展。

import numpy as np
import pandas as pd
import re

data = {'TextVar' : ['this should never match',
'matches foo bar',
'this is the second random pattern',
np.nan,
'foo bars, should return 0',
'foo bar, with a comma, should return 1']}

df = pd.DataFrame(data)
patterns = ['foo bar', 'second random pattern', 'pink unicorns',]

def stringFound(string1, string2):
    """
    string1 = pattern to look for
    string2 = string to look in
    """
    if pd.isnull(string1) or pd.isnull(string2):
        return False
    if re.search(r"\b" + re.escape(string1) + r"\b", string2):
        return True
    return False

def hasPattern(pattern_list, text):
    for e in pattern_list:
       if stringFound(e, text):
           return 1        
    return 0

df['Output'] = df.apply(lambda x :hasPattern(patterns, x['TextVar']), axis=1)

我尝试在5000个序列(len(patterns) = 5000)的列表上运行它,并在数据帧中运行15000行,30分钟后它仍在运行。我意识到我实际上已经迭代了7500万次 - 为了更有效率,我怎么写这个呢?

1 个答案:

答案 0 :(得分:1)

In [16]: pat = '|'.join([r'\b{}\b'.format(x) for x in patterns])

In [17]: pat
Out[17]: '\\bfoo bar\\b|\\bsecond random pattern\\b|\\bpink unicorns\\b'

In [18]: df['TextVar'].fillna('').str.contains(pat).astype(np.int8)
Out[18]:
0    0
1    1
2    1
3    0
4    0
5    1
Name: TextVar, dtype: int8

如果使用更复杂的模式,请尝试使用@Wiktor Stribiżew中的模式:

pat = r'(?<!\w){}(?!\w)'.format('|'.join([re.escape(m) for m in patterns]))