Биграм Finder для Панды Dataframe - PullRequest
2 голосов
/ 14 июня 2019

У меня есть список биграмм.
У меня есть фрейм данных pandas, содержащий строку для каждого документа в моем корпусе.То, что я хочу сделать, это получить биграммы, которые соответствуют из моего списка в каждом документе, в новый столбец в моем фрейме данных.Каков наилучший способ выполнить эту задачу?Я искал ответы на переполнение стека, но не нашел то, что дает мне конкретный ответ, который я ищу.Мне нужен новый столбец, который будет содержать каждый биграмм, найденный в моем списке биграмм.

Любая помощь будет оценена!

Вывод, который я имею ниже, - это то, что я ищу, хотя на моем реальном примере я использовал стоп-слова, поэтому точные биграммы не найдены, как вывод ниже.Есть ли способ сделать с какой-то строкой может быть?

import pandas as pd 
data = [['help me with my python pandas please'], ['machine learning is fun using svd with sklearn']] 
# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['Message']) 
import numpy as np
bigrams =[('python', 'pandas'),
 ('function', 'input'),
 ('help', 'jupyter'),
 ('sklearn', 'svd')]
def matcher(x):
    for i in bigrams:
        if i.lower() in x.lower():
            return i
    else:
        return np.nan

df['Match'] = df['Message'].apply(matcher)
df

Ответы [ 3 ]

2 голосов
/ 14 июня 2019

Вот что я бы сделал:

# a sample, which you should've given
df = pd.DataFrame({'sentences': ['I like python pandas', 
                                 'find all function input from help jupyter',
                                 'this has no bigrams']})

Или вы можете использовать get_dummies:

new_df.str.join(',').str.get_dummies(sep=',')

, что дает вам:

   function input  help jupyter  python pandas
0               0             0              1
1               1             1              0
2               0             0              0

# the bigrams
bigrams = [('python', 'pandas'),
 ('function', 'input'),
 ('help', 'jupyter'),
 ('sklearn', 'svd')]

# create one big regex pattern:
pat = '|'.join(" ".join(x) for x in bigrams)

new_df = df.sentences.str.findall(pat)

даетВы

0                   [python pandas]
1    [function input, help jupyter]
2                                []
Name: sentences, dtype: object

Затем вы можете выбрать unnest список в каждой строке.

Или вы можете использовать get_dummies:

new_df.str.join(',').str.get_dummies(sep=',')

который дает вам:

  function input  help jupyter  python pandas
0               0             0              1
1               1             1              0
2               0             0              0
1 голос
/ 15 июня 2019

flashtext также может быть использован для решения этой проблемы

import pandas as pd
from flashtext import KeywordProcessor
from nltk.corpus import stopwords

stop = stopwords.words('english')
bigram_token = ['python pandas','function input', 'help jupyter','svd sklearn']

data = [['help me with my python pandas please'], ['machine learning is fun using svd 
with sklearn']] 

# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['Message']) 

kp = KeywordProcessor()
kp.add_keywords_from_list(bigram_token)

def bigram_finder(x, stop, kp):
    token = x.split()
    sent = ' '.join([x for x in token if x not in stop])
    return kp.extract_keywords(sent)

df['bigram_token'] = df['Message'].apply(lambda x : bigram_finder(x, stop, kp))
#ouptput
 0    [python pandas]
 1      [svd sklearn]
 Name: bigram_token, dtype: object
1 голос
/ 15 июня 2019

Хорошо, вот мое решение, включающее определение биграммных терминов в очищенных высказываниях (предложениях).

Его также можно легко обобщить до 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)]

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...