Хорошо, вот мое решение, включающее определение биграммных терминов в очищенных высказываниях (предложениях).
Его также можно легко обобщить до n-граммов.Он также учитывает стоп-слова.
Вы можете настроить:
- target_depth (по умолчанию 2 для биграмм), если вы хотите искать n-граммы другого типа.
- разделитель (пробел) по умолчанию, используемый для токенизации слов в предложении.
- ваш набор стоп-слов (здесь используется nltk для общих английских остановок).
Обратите внимание, что эта реализацияявляется рекурсивным.
import pandas as pd
import re
from nltk.corpus import stopwords
data = [
['help me with my python pandas please'],
['machine learning is fun using svd with sklearn'],
['please use |svd| with sklearn, get help on JupyteR!']
]
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['Message'])
bigrams =[
('python', 'pandas'),
('function', 'input'),
('help', 'jupyter'),
('svd', 'sklearn')
]
stop_words = set(stopwords.words('english'))
sep = ' '
def _cleanup_token(w):
""" Cleanup a token by stripping special chars """
return re.sub('[^A-Za-z0-9]+', '', w)
def _preprocessed_tokens(x):
""" Preprocess a sentence. """
return list(map(lambda w: _cleanup_token(w), x.lower().split(sep)))
def _match_bg_term_in_sentence(bg, x, depth, target_depth=2):
""" """
if depth == target_depth:
return True # the whole bigram was matched
term = bg[depth]
term = term.lower()
pp_tokens = _preprocessed_tokens(x)
if term in pp_tokens:
bg_idx = pp_tokens.index(term)
if depth > 0 and any([token not in stop_words for token in pp_tokens[0:bg_idx]]):
return False # no bigram detected
x = sep.join(pp_tokens[bg_idx+1:])
return _match_bg_term_in_sentence(bg, x, depth+1, target_depth=target_depth)
else:
return False
def matcher(x):
""" Return list of bigrams matched in sentence x """
depth = 0 # current depth
matchs = []
for bg in bigrams:
bg_idx = 0 # first term
bg_matchs = _match_bg_term_in_sentence(bg, x, depth, target_depth=2)
if bg_matchs is True:
matchs.append(bg)
return matchs
df['Match'] = df['Message'].apply(matcher)
print(df.head())
На самом деле мы получаем следующие результаты:
Match
0 [(python, pandas)]
1 [(svd, sklearn)]
2 [(help, jupyter), (svd, sklearn)]
Надеюсь, это поможет!