You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用列表推导式实现词干提取?解决三类文本预处理问题

解决文本处理中的三个问题

问题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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:45:03