从我的分析中,我可以看到此函数需要更多时间来处理。如何加快此代码的速度?我的数据集有超过一百万条记录,这里我给出的这个停用词列表只是一个样本 - 它实际上包含150个单词。
def remove_if_name_v1(s):
stopwords = ('western spring','western sprin','western spri','western spr','western sp','western s',
'grey lynn','grey lyn','grey ly','grey l')
for word in stopwords:
s = re.sub(r'(' + word + r'.*?|.*?)\b' + word + r'\b', r'\1', s.lower(), 1)
return s.title()
test.new_name = test.old_name.apply(lambda x: remove_if_name_v2(x) if pd.notnull(x) else x)
似乎函数是为数据框中的每一行运行的,并且在每一行中,它运行for循环的次数与停用词一样多。有没有替代方法?
我在这里要做的就是例子,如果字符串包含“西部春路西部春天”,这个功能将返回“西部春天路”。
感谢。
答案 0 :(得分:3)
您可以组合并预编译正则表达式,以获得相当大的改进。
stopwords = ('western spring',
'western sprin',
'western spri',
'western spr',
'western sp',
'western s',
'grey lynn',
'grey lyn',
'grey ly',
'grey l')
pat = re.compile(r'(?P<repl>(?P<word>{stopwords}).*?|.*?)\b(?P=word)\b'.format(
stopwords='|'.join(re.escape(s) for s in stopwords)))
test.old_name.str.replace(pat, '\g<repl>')
请注意(?P=word)
反向引用。我还使用了Series.str.replace
代替Series.apply
,后者稍微清晰了。
答案 1 :(得分:2)
一个快速的改进是将停用词放在一组中。检查时,多个单词将导致一个恒定的时间O(1)查找。
STOP_WORDS = {
'western spring',
'western sprin',
'western spri',
'western spr',
'western sp',
'western s',
'grey lynn',
'grey lyn',
'grey ly',
'grey l'
}
def find_first_stop(words):
if len(words) == 0:
return False
joined = ' '.join(reversed(words))
if joined in STOP_WORDS:
return True
return find_first_stop(words[:-len(words) - 1])
def remove_if_name_v1(s):
if s in STOP_WORDS:
return s
words = []
split_words = s.split(' ')
for word in reversed(split_words):
words.append(word)
if find_first_stop(words):
words = []
return ' '.join(reversed(words))
old_name = pd.Series(['western spring road western spring', 'kings road western spring', 'western spring'])
new_name = old_name.apply(lambda x: remove_if_name_v1(x) if pd.notnull(x) else x)
print(new_name)
输出:
0 western spring road
1 kings road
2 western spring
dtype: object