pandas 在Python中使用单词计数器会低估结果

mzmfm0qo  于 2023-11-15  发布在  Python
关注(0)|答案(1)|浏览(100)

作为一个完整的序言,我是一个初学者和学习。但是,这里是我的产品评论表的示例模式。
| 记录ID|产品编号|审查意见|
| --|--|--|
| 1234 | 89847457 |我喜欢这个产品,它运得快,很舒服|
这是我的代码。它给了我所有评论的总字数,以及另一个短语的计数,以尝试获得更多的上下文.即('flimsy','tight')如果衬衫的合身是紧身的,质量是脆弱的。脚本编写一个新的Excel文档,其中包含两者的计数。

import pandas as pd
from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
import string
from collections import Counter
from nltk.util import ngrams
import nltk
nltk.download('punkt')

df = pd.read_excel('productsvydata.xlsx')

def preprocess_text(text):
    translator = str.maketrans('', '', string.punctuation)
    text = text.lower() 
    text = text.translate(translator)
    return text

word_counts = {}
phrase_counts = {}

unique_product_ids = df["Product_ID"].unique()

# Set the number of top words and phrases you want to keep
top_n = 100

for selected_product_id in unique_product_ids:
    selected_comments_df = df[df["Product_ID"] == selected_product_id]
    selected_comments = ' '.join(selected_comments_df["Product Review Comment"].astype(str))
    selected_comments = preprocess_text(selected_comments)
    if not selected_comments.strip():
        continue
    tokenized_words = nltk.word_tokenize(selected_comments)
    stop_words = set(ENGLISH_STOP_WORDS)
    filtered_words = [word for word in tokenized_words if word not in stop_words]
    lemmatizer = nltk.WordNetLemmatizer()
    lemmatized_words = [lemmatizer.lemmatize(word) for word in filtered_words]
    max_phrase_length = 4
    phrases = [phrase for n in range(2, max_phrase_length + 1) for phrase in ngrams(lemmatized_words, n)]
    word_counter = Counter(lemmatized_words)
    phrase_counter = Counter(phrases)

    # Get the top N words and phrases
    top_words = dict(word_counter.most_common(top_n))
    top_phrases = dict(phrase_counter.most_common(top_n))

    # Extract record_id for each Product_ID
    record_ids = selected_comments_df["record_id"].values[0]

    word_counts[(selected_product_id, record_ids)] = top_words
    phrase_counts[(selected_product_id, record_ids)] = top_phrases

word_result_data = []
phrase_result_data = []

for (product_id, record_id), top_words in word_counts.items():
    for word, count in top_words.items():
        word_result_data.append([product_id, record_id, word, count])
for (product_id, record_id), top_phrases in phrase_counts.items():
    for phrase, count in top_phrases.items():
        phrase_result_data.append([product_id, record_id, phrase, count])

word_df = pd.DataFrame(word_result_data, columns=['Product_ID', 'record_id', 'Word', 'Count'])
phrase_df = pd.DataFrame(phrase_result_data, columns=['Product_ID', 'record_id', 'Phrase', 'Count'])

word_df.to_csv('top_words_counts.csv', index=False)
phrase_df.to_csv('top_phrases_counts.csv', index=False)

字符串
我使用top_n = 100来获取导出中的前100个单词,因为有超过20,000行数据,如果我做了所有的单词和短语,它将无法运行。它需要使用产品ID和记录ID,因为这是它在我的工作工具中加入的内容。
问题是,我觉得结果被低估了。我想知道这是否与标记化有关。例如,现在我在这个导出中的数据中有9个单词“客户”的示例。在短语count中,('customer','service')出现得更少。如果我只是通过原始文档中的原始Product Review Comments来控制F,有更多的人谈论客户服务的例子。在处理过程中出了问题,但我不知道是什么。
有没有人能提供一些建议,让我们更好地优化这段代码,同时产生更多的结果?这是一个非常基本的NLP,但同样,我是新来的,我想学习,但我在输出中遇到了一个障碍。

7kjnsjlb

7kjnsjlb1#

虽然这会使词形化变得更困难,但我总是推荐使用sklearn的CountVectorizer,它包括停止字删除,而不是使用nltk和base python的艰难方法。
此外,在预处理中,您可以使用apply方法一次性对整个评论列进行更有效的预处理。我建议您不需要将每个产品的所有评论都加入,然后进行标记;而是为每个记录进行单词/ n-gram计数,然后通过按产品ID分组对计数进行求和就可以了:

# Preprocess the review column
df['Product Review Comment'] = df['Product Review Comment'].apply(preprocess_text)

# Instantiate CountVectorizer
cv = CountVectorizer(stop_words='english', min_df=100, ngram_range=(1,5))

# Create document-term dataframe of word counts per record 
dtm = cv.fit_transform(df['Product Review Comment'])
dtm_df = pd.DataFrame(dtm.todense(), columns=cv.get_feature_names_out())

# Join to the original data
joined_df = pd.concat([df, dtm_df], axis=1)

# Find the sum of word counts per product
word_count_df = joined_df.groupby('Product_ID').sum().drop('Record_ID', axis=1).reset_index()

# Flatten / convert DTM from wide format to long format
long_df = pd.melt(word_count_df, id_vars=['Product_ID'], var_name='var', value_name='value')

# Find 100 top words per product
long_df.groupby('Product_ID').head(100)

字符串
对于词形化,您需要编写自己的tokenizer函数,其中包含它并在tokenizer参数中传入CountVectorizer。此外,如果您有一个大型数据集,您可能希望将min_df设置得更高,以便您的文档项矩阵不会变得非常大,但是,如果您只是担心顶部项(整个数据集),那么这应该是可以的。
希望这对你有帮助!

相关问题