Как подсчитать конкретные термины в токенизированных предложениях с помощью pandas df

Я новичок в Python и nltk, поэтому был бы очень признателен за ваш вклад в решение следующей проблемы.

Цель:

Я хочу найти и подсчитать появление определенной терминологии в токенизированных предложениях, которые хранятся в pandas DataFrame. Термины, которые я ищу, хранятся в списке строк. Вывод следует сохранить в новом столбце.

Поскольку слова, которые я ищу, имеют грамматические наклонения (например, кошки вместо кошки), мне нужно решение, которое не только отображает точные совпадения. Я предполагаю, что выделение данных и поиск определенных основ было бы правильным подходом, но давайте предположим, что это не вариант, поскольку у нас все равно будут семантические совпадения.

Что я пробовал на данный момент:

Для дальнейшей обработки данных я предварительно обработал данные, выполнив следующие действия:

  1. Поместите все в нижний регистр
  2. Удалить знаки препинания
  3. Токенизация
  4. Удалить стоп-слова

Я попытался найти отдельные термины с помощью str.count('cat'), но это не помогло, и данные были помечены как отсутствующие с помощью NaN. Кроме того, я не знаю, как эффективно перебирать список слов для поиска при использовании pandas.

Мой код на данный момент:

import numpy as np
import pandas as pd
import re
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords

# Function to remove punctuation
def remove_punctuation(text):
    return re.sub(r'[^\w\s]','',text)


# Target data where strings should be searched and counted
data = {'txt_body': ['Ab likes dogs.', 'Bc likes cats.',
                     'De likes cats and dogs.', 'Fg likes cats, dogs and cows.',
                     'Hi has two grey cats, a brown cat and two dogs.']}


df = pd.DataFrame(data=data)

# Search words stored in a list of strings
search_words = ['dog', 'cat', 'cow']

# Store stopwords from nltk.corpus
stop_words = set(stopwords.words('english'))

# Data preprocessing
df['txt_body'] = df['txt_body'].apply(lambda x: x.lower())
df['txt_body'] = df['txt_body'].apply(remove_punctuation)
df['txt_body'] = df['txt_body'].fillna("").map(word_tokenize)
df['txt_body'] = df['txt_body'].apply(lambda x: [word for word in x if word not in stop_words])

# Here is the problem space
df['search_count'] = df['txt_body'].str.count('cat')



print(df.head())

Ожидаемый результат:

                                       txt_body  search_count
0                             [ab, likes, dogs]             1
1                             [bc, likes, cats]             1
2                       [de, likes, cats, dogs]             2
3                 [fg, likes, cats, dogs, cows]             3
4  [hi, two, grey, cats, brown, cat, two, dogs]             3

Хотите считать префиксы? В противном случае вам придется лемматизировать или выполнять некоторую обработку токенов …   —  person cru-436    schedule 15.12.2020

См. также:  VSCode + Pytest: ошибка: TypeError: невозможно прочитать свойство $ неопределенного значения

Привет! Да, было бы хорошо считать только части самого слова. Лемматизация — это небольшая проблема, поскольку я ищу решение, которое также можно было бы применить с неанглийским набором данных. Но стемминг не должен быть проблемой … Что бы вы посоветовали?   —  person cru-436    schedule 15.12.2020

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. cru-436

    Очень простое решение:

    def count_occurence(l, s):
        counter = 0
        for item in l:
            if s in item:
                counter += 1
        return counter
    
    df['search_count'] = df.apply(lambda row: count_occurence(row.txt_body, 'cat'),1)
    

    Затем вы можете решить, как определить функцию count_occurence. И, чтобы искать все search_words, что-то вроде этого сработает, хотя, вероятно, это не самый эффективный вариант:

    def count_search_words(l, search_words):
        counter = 0
        for s in search_words:
            counter += count_occurence(l, s)
        return counter
    
    df['search_count'] = df.apply(lambda row: count_search_words(row.txt_body, search_words),1)  
    

    Спасибо! Да, это работает для одной струны. Как бы вы перебрали строки в списке search_words и суммировали результаты для всех трех терминов? У меня проблемы с поиском подходящего решения. person cru-436; 15.12.2020

    вы проверили мой отредактированный ответ? person cru-436; 15.12.2020

    Ах, прости. Я не обновлял страницу. Да, определенно работает. Спасибо еще раз! Вопрос об эффективности определенно актуален, поскольку я планирую применить его к довольно большому набору данных. Но предварительная обработка уже занимает некоторое время, так что пока все должно быть в порядке. Есть ли у вас догадки, как может выглядеть более эффективный подход? person cru-436; 15.12.2020

    Вероятно, это будет хорошо, если search_words не станет огромным. person cru-436; 15.12.2020

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: