Python:如何基于词元列表列表生成Bag of Words
当然可以!完全不用放弃你自己用NLTK搭的预处理流程,scikit-learn其实给了很灵活的方式来适配你已经处理好的词元列表。下面给你两种实用的解决方案:
方法1:给CountVectorizer“开绿灯”,直接用你的词元列表
这是最省心的方式——CountVectorizer默认会对输入字符串做分词,但我们可以通过参数设置,让它跳过自带的预处理/分词步骤,直接用你已经处理好的词元列表来统计词频。
先假设你的预处理后的数据是这样的:
import pandas as pd from sklearn.feature_extraction.text import CountVectorizer # 你的DataFrame,processed_text列是已经处理好的词元列表 df = pd.DataFrame({ 'processed_text': [["hello", "world"], ["hello", "stackoverflow", "hello"]] })
接下来只需要给CountVectorizer设置两个关键参数:
# 让CountVectorizer直接使用我们的词元列表,不做额外处理 vectorizer = CountVectorizer( preprocessor=lambda x: x, # 跳过预处理步骤 tokenizer=lambda x: x # 跳过分词步骤,直接返回输入的词元列表 ) # 拟合数据并生成Bag of Words矩阵 bow_matrix = vectorizer.fit_transform(df['processed_text']) # 查看生成的词汇表 print(vectorizer.get_feature_names_out()) # 输出: ['hello' 'stackoverflow' 'world'] # 把稀疏矩阵转为普通数组查看结果 print(bow_matrix.toarray()) # 输出: # [[1 0 1] # [2 1 0]]
这里的核心是用lambda x: x把预处理和分词步骤都替换成“原样返回”,这样CountVectorizer就会直接拿你的词元列表来统计词频,完全保留你之前用NLTK做的分词、去停用词、词干提取的结果。而且你还能继续用CountVectorizer的其他功能,比如min_df过滤低频词,完全不冲突。
方法2:手动统计词频(适合需要高度自定义的场景)
如果你想完全掌控整个流程,也可以手动构建词汇表并统计每个文档的词频,灵活性拉满:
from collections import defaultdict import numpy as np # 第一步:从所有文档里构建词汇表 all_words = [word for doc in df['processed_text'] for word in doc] vocab = sorted(list(set(all_words))) # 排序保证词汇表顺序一致 vocab_map = {word: idx for idx, word in enumerate(vocab)} # 第二步:逐个文档统计词频,生成Bag of Words向量 bow_vectors = [] for doc in df['processed_text']: word_counts = defaultdict(int) for word in doc: word_counts[word] += 1 # 按照词汇表的顺序生成向量,不存在的词计数为0 current_vector = [word_counts.get(word, 0) for word in vocab] bow_vectors.append(current_vector) # 转为numpy数组方便后续处理 bow_matrix = np.array(bow_vectors) print(vocab) # 输出: ['hello', 'stackoverflow', 'world'] print(bow_matrix) # 输出: # [[1 0 1] # [2 1 0]]
这种方法适合你需要在统计词频前后加自定义逻辑的场景,比如手动过滤某些特定词汇、调整计数规则等等。
额外提示
如果之后你要做TF-IDF转换,同样可以用TfidfVectorizer,设置相同的preprocessor和tokenizer参数就行,完全兼容你的预处理流程。
内容的提问来源于stack exchange,提问作者Florian
相关产品推荐
相关产品推荐

