必须先对每列文本清洗(去空值、转字符串、strip)、再逐单元格调用jieba.lcut(),推荐用try-except封装;停用词应从相对路径文件加载为set;词频统计宜用Counter处理已过滤的token列表,而非CountVectorizer。

用 jieba 对多列文本批量分词,别直接传 DataFrame
直接把 pandas.DataFrame 丢给 jieba.lcut() 会报 TypeError: expected string or bytes-like object——jieba 只认单个字符串。必须先按列取出,再逐行、逐单元格处理。
常见错误是写成 df['col'].apply(jieba.lcut) 却忘了清洗:空值、数字、NaN 会直接崩。实操建议:
- 先用
df[col].dropna().astype(str)强制转字符串并剔除空值 - 对每行做
strip()去首尾空白,避免切出空字符串 - 加
try...except包裹jieba.lcut(),捕获异常后返回空列表,保全流程不中断 - 示例:
def safe_cut(text): try: return jieba.lcut(text.strip()) except: return [] df['col_tokens'] = df['col'].dropna().astype(str).apply(safe_cut)
合并多列 token 后去停用词,别硬编码停用词表路径
多列分词后通常要汇总统计(比如“用户评论+标题+标签”一起看高频词),这时停用词过滤必须统一且可维护。硬写 stopwords = ['的', '了', '在'] 很容易漏、难更新。
更稳妥的做法:
立即学习“Python免费学习笔记(深入)”;
- 用
os.path.join(os.path.dirname(__file__), 'stopwords.txt')相对路径读取本地文件,避免绝对路径迁移失败 - 停用词文件每行一个词,用
set(line.strip() for line in open(path))加载,提升in查询性能 - 注意中文标点(如‘,’‘。’‘!’)也要加入停用词集,否则会大量出现在词频里
- 若列间语义差异大(如“商品描述”和“客服对话”),考虑分列加载不同停用词表,而非强行共用
用 collections.Counter 统计词频,慎用 sklearn.feature_extraction.text.CountVectorizer
CountVectorizer 看似省事,但它默认做小写转换、正则过滤、n-gram 拆分,对中文几乎无效,还强制要求输入是字符串列表而非 token 列表——你得先 ' '.join(tokens) 拼回去,再喂给它,纯属绕路。
真实高效做法是直接处理 token 列表:
- 把所有列的 token 列表拼成一个大列表:
all_tokens = sum(df['col1_tokens'].tolist() + df['col2_tokens'].tolist(), []) - 用
Counter(all_tokens)得到词频字典,再.most_common(100)取 Top 100 - 如果要导出为 DataFrame 方便筛选,用
pd.DataFrame(Counter(...).items(), columns=['word', 'count']) - 注意:
Counter不自动过滤停用词,必须在all_tokens构建阶段就过滤,比如:all_tokens = [w for tokens in df['col_tokens'] for w in tokens if w not in stopwords]
处理长尾词和低频噪声,不能只靠词频阈值
设 min_count=2 看似能去噪,但中文常有“用户ID+编号”类组合词(如“张三20240501”),它们必然低频、无意义,却不会被词频过滤掉。
真正有效的清理策略是分层过滤:
- 长度过滤:去掉
len(word) == 1的单字(除非业务强依赖,如“U盘”里的“U”),也去掉超长词(len(word) > 10) - 字符类型检查:用
re.match(r'^[\u4e00-\u9fa5a-zA-Z0-9]+$', word)排除含特殊符号的词(如“苹果#新品”里的“苹果#新品”) - 业务关键词白名单:把必须保留的术语(如产品型号“iPhone15Pro”)提前加入集合,避免被规则误杀
- 不要依赖
jieba.add_word()临时加词——它只影响后续分词,对已分好的 token 无效;该操作应在分词前集中完成


















