使用pandas、gensim预处理数据遇TypeError如何解决
pandas+gensim 数据预处理标准流程与TypeError排查方案
标准预处理流程
全流程按顺序执行,可覆盖90%以上文本类任务的预处理需求:
- 数据读入与初筛
数据源导入pandas后第一步先做类型校验,不要着急跑后续逻辑:- 执行
df.info()打印全字段信息,重点确认目标文本列的类型、空值占比,object类型列要提前排查是否混入数值、None、嵌套结构等非字符串内容,这是后续报错的核心诱因 - 空值统一填充:文本列用
df['target_text'] = df['target_text'].fillna('')把所有NaN替换为空字符串,gensim所有文本处理接口都无法识别pandas的NaN值,碰到必抛类型错误 - 剔除冗余字段,仅保留任务必需的id、文本、标签字段,减少无关字段的类型干扰
- 执行
- 文本标准化
所有文本规整操作优先用pandas内置的str向量化接口实现,效率比逐行循环高一个量级:- 统一字符大小写(英文场景必做):
df['target_text'] = df['target_text'].str.lower() - 清洗无效字符:用正则移除特殊符号、多余空白,参考代码:
df['target_text'] = df['target_text'].str.replace(r'[^\w\s]', '', regex=True)\ .str.replace(r'\s+', ' ', regex=True)\ .str.strip() - 分词与停用词过滤:分词时加
str()做类型兜底,彻底规避非字符串输入问题,参考代码(中文场景用jieba,英文场景替换为nltk分词即可):import jieba stop_words = set([line.strip() for line in open('stopwords.txt', encoding='utf-8')]) df['token_list'] = df['target_text'].apply( lambda x: [w for w in jieba.lcut(str(x)) if w not in stop_words and len(w) > 1] )
- 统一字符大小写(英文场景必做):
- gensim格式适配
预处理完的pandas结果不要直接传gensim接口,先转成Python原生数据结构:- 构建语料词典:
from gensim import corpora; dct = corpora.Dictionary(df['token_list'].tolist()) - 过滤极端值降低噪声:
dct.filter_extremes(no_below=5, no_above=0.8, keep_n=10000) - 生成BOW语料:
corpus = [dct.doc2bow(tokens) for tokens in df['token_list'].tolist()]
到这一步输出的词典和语料可以直接对接LDA、Word2Vec等所有gensim模型。
- 构建语料词典:
TypeError高频根源排查
按出现概率从高到低排序,逐一核对即可定位问题:
- 文本列混入非字符串值:sql导出的数据很容易出现部分行文本字段存了数值、NULL、二进制内容的情况,执行
df[~df['target_text'].apply(lambda x: isinstance(x, str))]可以直接筛出所有非字符串的异常行,统一转字符串或者剔除即可 - 分词结果存在无效值:如果某行文本清洗后为空,分词后会返回空列表,或者apply逻辑异常返回None,传给
doc2bow、词典构建接口时会触发类型错误,执行df = df[df['token_list'].apply(lambda x: isinstance(x, list) and len(x) > 0)]过滤掉无效分词行即可 - 类型兼容问题:pandas 2.0+版本新增的StringDtype无法被旧版本gensim识别,会被判定为非字符串类型,执行
df['target_text'] = df['target_text'].astype(str).astype(object)把列转回传统object类型即可解决 - 传参类型错误:gensim大部分接口不支持直接传入pandas的Series、DataFrame对象,如果传参时没加
.tolist()转成原生Python列表,也会触发类型错误,所有传给gensim的序列类参数都先转成原生列表即可。
内容的提问来源于stack exchange,提问作者Akiira
相关产品推荐
相关产品推荐

