使用NLTK去除停用词失败求助:分词正常但停用词未移除
问题分析与解决
你的停用词移除功能失效主要有两个核心问题:
- return语句位置错误:
remove_stopwords函数里的return text写在for循环内部,导致循环只执行一次就直接返回结果,根本没遍历完所有单词,自然没法移除所有停用词。 - 遍历列表时直接修改原列表的风险:用
for word in text遍历同时执行text.remove(word),会导致迭代器跳过部分元素,即使修正return位置,也可能出现漏删的情况。
另外你的预处理函数还会产生空字符串,建议一并处理。
修正后的完整代码
import re import nltk from nltk.corpus import stopwords def pre_process(text): # 移除特殊字符和数字 text = re.sub(r"(\d|\W|_)+", " ", text) # 分词并过滤空字符串 text = [word for word in re.split(r"\W+", text) if word] return text # 下载停用词 nltk.download('stopwords') # 转成集合提升查询效率 stop_words = set(stopwords.words('english')) def remove_stopwords(text): # 用列表推导式生成不含停用词的新列表,避免修改原列表导致的迭代问题 return [word for word in text if word not in stop_words] # 应用预处理和停用词移除 text = dat['text'].apply(lambda x: pre_process(x)) text_stopword = text.apply(lambda x: remove_stopwords(x))
关键修改说明
- 调整return位置:把返回逻辑移到循环外部(直接用列表推导式替代循环更简洁),确保所有单词都被检查。
- 改用集合存储停用词:
stopwords.words('english')是列表,查询word in 列表的时间复杂度是O(n),转成集合后是O(1),处理大量数据时效率更高。 - 过滤空字符串:预处理时用列表推导式过滤掉
re.split产生的空字符串,避免后续处理无效内容。 - 用列表推导式替代循环删除:直接生成新的不含停用词的列表,比遍历删除原列表更安全、高效,不会出现迭代跳过元素的问题。
测试修正后的代码,the、in、of这类停用词就会被正确移除了。
内容的提问来源于stack exchange,提问作者Jeren Suen
相关产品推荐
相关产品推荐

