Я пытаюсь получить частоту слов в тексте твита из CSV-файла, используя подсчет значений pandas.

Вот мой код:

import nltk
from nltk.corpus import stopwords
from nltk.tokenize import RegexpTokenizer
from nltk.stem import WordNetLemmatizer
import pandas as pd
import numpy as np
import openpyxl
import string

tokenizer = RegexpTokenizer(r'\w+')
lemmatizer = WordNetLemmatizer()


def remove_stopwords(df_text):
    words = [w for w in df_text if w not in stopwords.words('english')]
    return words

def word_lemmatizer(df_text):
    lem_text = [lemmatizer.lemmatize(i) for i in df_text]
    return lem_text

#works fine from here
df = pd.read_csv('amazonfresh-test.csv', encoding='utf-8', converters={'text': str})


df['text'].apply(lambda x: tokenizer.tokenize(x.lower()))
df['text'].apply(lambda x: remove_stopwords(x))
df['text'].apply(lambda x: word_lemmatizer(x))

#to here

#this is where I have issues
data_count = df['test'].apply(pd.value_counts())

data_count.to_excel("amazonfresh-test.xlsx")

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

Вот как выглядит файл csv:

Вот новый CSV-файл со словами в собственной ячейке, все еще пытающийся получить значение value_count для этого.< /а>


person Tom    schedule 22.06.2020    source источник
comment
Можете ли вы предоставить образец 'amazonfresh-test.csv'?   -  person Phillyclause89    schedule 23.06.2020
comment
Да, только что @Phillyclause89   -  person Tom    schedule 23.06.2020
comment
Спасибо за скриншот csv. Откуда вы берете столбец 'test' в data_count = df['test'].apply(pd.value_counts())? Я не вижу это как столбец, существующий в вашем исходном CSV, и я не вижу, чтобы вы создавали такой столбец где-либо в своем коде, прежде чем использовать для него метод pandas.Series.apply.   -  person Phillyclause89    schedule 23.06.2020
comment
@ Phillyclause89, должно быть, это была опечатка, это была ссылка на столбец «текст» в CSV   -  person Tom    schedule 23.06.2020
comment
Была ли эта опечатка причиной вашей проблемы или поведение, которое вы отметили в этом вопросе, происходит без опечатки в коде?   -  person Phillyclause89    schedule 23.06.2020
comment
@ Phillyclause89 это происходит без опечатки. Я могу лемматизировать, удалять стоп-слова и токенизировать без особых проблем. Но у меня проблема, просто пытаясь подсчитать значение текста в столбце.   -  person Tom    schedule 23.06.2020
comment
также я не знаком с методом pandas.value_counts. Есть pandas.Series.value_counts, но я не уверен, что это то, что вы хотите здесь использовать. вы просто пытаетесь подсчитать количество каждого токена, оставшегося после удаления стоп-слов? может попробовать: data_count = df['text'].apply(lambda x: len(x))?   -  person Phillyclause89    schedule 23.06.2020
comment
@Phillyclause89 Phillyclause89 программа, кажется, работает абсурдно долго, есть предположения, почему?   -  person Tom    schedule 23.06.2020
comment
@ Phillyclause89 да, просто пытаюсь подсчитать оставшиеся жетоны, предложенный вами скрипт выводит только числа   -  person Tom    schedule 23.06.2020
comment
Думаю, я понимаю, что вы здесь ищете. Мне потребовалась секунда, чтобы установить все пакеты nltk, но теперь я готов к работе с вашим скриптом. Можете ли вы подтвердить, что вы на самом деле нажимаете на строку #это, где у меня есть проблемы, и есть ли в строке ниже действительно data_count = df['text'].apply(pd.value_counts()) или в этой строке есть другие опечатки? как написано, я получаю TypeError: value_counts() missing 1 required positional argument: 'values', когда пытаюсь запустить его. Как вы определили, что эта линия является вашим узким местом? Вы уверены, что это не один из других .apply вызовов?   -  person Phillyclause89    schedule 23.06.2020
comment
Итак, две идеи после игры с этим. 1) имейте в виду, что pandas.Series.apply по умолчанию не является методом на месте. Я думаю, вы хотите сделать df['text'] = df['text'].apply(func) в тех трех строках, где, похоже, вы хотите токонизировать и отфильтровать данные в текстовом столбце. 2) Я думаю, вы хотите удалить вызывающую функцию из функции pd.value_counts в строке data_count = df['test'].apply(pd.value_counts()). попробовать сделать data_count = df['test'].apply(pd.value_counts)?   -  person Phillyclause89    schedule 23.06.2020
comment
@ Phillyclause89 Хорошо, поэтому я смог вывести CSV-файл, в котором каждое слово было разделено на отдельную ячейку, как мне тогда использовать подсчет значений? Я прикреплю новый csv к исходному сообщению.   -  person Tom    schedule 23.06.2020


Ответы (1)


После изрядного количества комментариев в комментариях с OP я решил, что будет лучше всего обобщить мои предложения здесь.

Первая проблема заключается в том, что в data_count = df['test'].apply(pd.value_counts()) есть две опечатки.

Эта строка на самом деле должна быть data_count = df['text'].apply(pd.value_counts).

df['test'] поднимет KeyError, так как в OP pandas.DataFrame нет столбца 'test'. Другая опечатка — безаргументный вызов pandas.value_counts в вызывающем методе pandas.Series.apply. Это вызовет TypeError из-за того, что функция pandas.value_counts требует хотя бы одного аргумента. Но это легко исправить, удалив вызывающую программу, поскольку смысл метода pandas.Series.apply состоит в том, чтобы он вызывал функцию для нас, используя каждое значение в ряду в качестве аргумента.

Следующая проблема, которую я заметил, связана с тремя другими вызовами метода pandas.Series.apply:

df['text'].apply(lambda x: tokenizer.tokenize(x.lower()))
df['text'].apply(lambda x: remove_stopwords(x))
df['text'].apply(lambda x: word_lemmatizer(x))

Эти три строки написаны так, как будто pandas.Series.apply является методом на месте, а это не так. Чтобы они действительно изменили объект pandas.DataFrame, назначенный df, здесь нужно использовать присваивание:

df['text'] = df['text'].apply(lambda x: tokenizer.tokenize(x.lower()))
df['text'] = df['text'].apply(remove_stopwords)
df['text'] = df['text'].apply(word_lemmatizer)

Кроме того, лямбда-выражение требуется только в первом вызове для выполнения части x.lower(), поскольку remove_stopwords и word_lemmatizer оба принимают значение как есть, нам не нужны дополнительные лямбда-выражения. Наконец, все три строки можно объединить в один вызов pandas.Series.apply, поскольку эти функции применяются к одним и тем же значениям:

df['text'] = df['text'].apply(
    lambda x: word_lemmatizer(
        remove_stopwords(
            tokenizer.tokenize(x.lower())
        )
    )
)

Полный код, который, я надеюсь, OP смог собрать из моих комментариев, должен выглядеть примерно так:

from nltk.corpus import stopwords
from nltk.tokenize import RegexpTokenizer
from nltk.stem import WordNetLemmatizer
import pandas as pd

tokenizer = RegexpTokenizer(r'\w+')
lemmatizer = WordNetLemmatizer()


def remove_stopwords(df_text):
    words = [w for w in df_text if w not in stopwords.words('english')]
    return words


def word_lemmatizer(df_text):
    lem_text = [lemmatizer.lemmatize(i) for i in df_text]
    return lem_text


df = pd.read_csv('test.csv', encoding='utf-8', converters={'text': str}, sep="\t")

df['text'] = df['text'].apply(
    lambda x: word_lemmatizer(
        remove_stopwords(
            tokenizer.tokenize(x.lower())
        )
    )
)

data_count = df['text'].apply(pd.value_counts)

data_count.to_excel("test.xlsx")

Созданный файл Excel должен выглядеть примерно так.

введите здесь описание изображения Примечание. Результат, показанный на моем снимке экрана, получен в результате выполнения этого кода в CSV-файле с одним столбцом, который состоит из первых 100 предложений книги «Дюна». потрудитесь воссоздать csv, показанный на скриншоте OP, поскольку единственное, что должно иметь значение, это наличие столбца с кучей английских слов с именем «текст»

Теперь, когда все это задокументировано в этом ответе, у OP все еще есть один неподтвержденный комментарий:

@ Phillyclause89 Хорошо, поэтому я смог вывести CSV-файл, в котором каждое слово было разделено на отдельную ячейку, как мне тогда использовать подсчет значений? Я прикреплю новый csv к исходному сообщению.

Я рекомендую использовать pandas.value_counts, как показано в приведенном выше примере кода (внутри pandas.Series.Apply и без его вызова). Оттуда вы можете использовать различные методы agg, такие как sum, чтобы найти количество слов во всех строках:

agg_data_count = data_count.sum().sort_values(0,ascending=False)
agg_data_count.to_excel("sums.xlsx")

Открыв sums.xlsx, мы можем получить хороший список наших слов и сколько раз они встречаются во всем наборе данных: введите здесь описание изображения

person Phillyclause89    schedule 24.06.2020
comment
также понял, что df['text'].value_counts() тоже работает, спасибо за вашу помощь! - person Tom; 24.06.2020