Ваш паттерн очень неэффективен, так как у него есть много незанятых альтернатив, начинающихся с идентичного паттерна, который может сильно откатиться назад. Кроме того, границы слов, которые вы хотите использовать, также должны отсортировать термины по длине в порядке убывания, чтобы найти самые длинные термины в случае их совпадения (например, Merceded
и Mercedes Benz
).
Итак, используйте
pattern = r'(?i)\b(?:{})\b'.format('|'.join(sorted(df["term"],key=len,reverse=True)))
Или, если у вас есть особые символы в терминах,
pattern = r'(?i)(?<!\w)(?:{})(?!\w)'.format('|'.join(map(re.escape, sorted(df["term"],key=len,reverse=True))))
, а затем
df["words"]= df["sentence"].str.findall(pattern)
df["sentence"].replace(pattern, r"\g<0>|present", inplace=True, regex=True)
Шаблон будет выглядеть как (?i)\b(?:Mercedes Benz|EXpensive|electric|TOYOTA|Ford|cars)\b
, он будет совпадать - в случае нечувствительности к регистру из-за (?i)
- целых слов Mercedes Benz
, EXpensive
, electric
, TOYOTA
, Ford
, cars
и в df["sentence"].str.findall(pattern)
этонайдет все непересекающиеся вхождения совпадения с образцом, и в df["sentence"].replace(pattern, r"\g<0>|present", inplace=True, regex=True)
все совпадения будут заменены на себя (\g<0>
- это обратная ссылка на все совпадение) + |present
, добавленные к ним.