如何用列表推导式实现词干提取?解决三类文本预处理问题
解决文本处理中的三个问题
问题a:移除空字符串
你之前用if word != " "无效,因为text.split()默认会分割所有空白字符,不会生成空格字符串。空字符串是处理后产生的(比如原单词全是标点,处理后变成空),所以要在处理完每个单词后判断是否非空。
问题b:保留连字符短语
直接用string.punctuation移除所有标点会删掉连字符,破坏像26-year-old这类合成词。可以用正则表达式只移除单词首尾的标点,保留单词内部的连字符:
re.sub(r'^[^\w\'-]+|[^\w\'-]+$', '', word)
这个正则会去掉单词开头/结尾的非字母、数字、撇号、连字符的字符,保留内部的合法符号。
问题c:正确处理缩写(如wasn't)
之前的方法会删掉撇号导致wasn't变成wasnt,用上面的正则可以保留撇号,之后词干化工具(比如PorterStemmer)会正确处理这类缩写(wasn't小写后是wasn't,词干化后会保留缩写的核心结构)。
修改后的完整代码
假设你用的是nltk的PorterStemmer,完整代码如下:
import re from nltk.stem import PorterStemmer stem = PorterStemmer().stem list_of_texts = [ [ stem(processed_word) for word in text.split() if (processed_word := re.sub(r'^[^\w\'-]+|[^\w\'-]+$', '', word.lower())) ] for text in list_of_texts ]
如果你的Python版本不支持海象运算符:=,可以拆分两步:
list_of_texts = [ [ stem(processed_word) for word in text.split() for processed_word in [re.sub(r'^[^\w\'-]+|[^\w\'-]+$', '', word.lower())] if processed_word ] for text in list_of_texts ]
说明
- 正则
^[^\w\'-]+匹配单词开头的非合法字符,[^\w\'-]+$匹配结尾的,用re.sub替换为空,保留内部的连字符和撇号。 - 处理后的单词通过
if processed_word过滤掉空字符串(空字符串在布尔判断中为False)。 - 词干化放在最后,确保处理后的合法单词再被词干化。
内容的提问来源于stack exchange,提问作者Andreas Rouvalis
相关产品推荐
相关产品推荐

