我有一个包含文本列的 pandas DataFrame
,我想使用 scikit-learn 的 CountVectorizer
来对文本进行向量化。然而,文本中包含缺失值,因此我想在向量化之前用一个常量值进行填补。
我的初步想法是创建一个由 SimpleImputer
和 CountVectorizer
组成的 Pipeline
:
import pandas as pdimport numpy as npdf = pd.DataFrame({'text':['abc def', 'abc ghi', np.nan]})from sklearn.impute import SimpleImputerimp = SimpleImputer(strategy='constant')from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer()from sklearn.pipeline import make_pipelinepipe = make_pipeline(imp, vect)pipe.fit_transform(df[['text']]).toarray()
然而,fit_transform
会报错,因为 SimpleImputer
输出的是一个二维数组,而 CountVectorizer
需要一维输入。这是错误信息:
AttributeError: 'numpy.ndarray' object has no attribute 'lower'
问题:我如何修改这个 Pipeline
使其正常工作?
注意:我知道我可以在 pandas 中填补缺失值。然而,我希望在 scikit-learn 中完成所有预处理,以便可以使用 Pipeline
对新数据应用相同的预处理。
回答:
我找到的最佳解决方案是在 Pipeline
中插入一个自定义转换器,将 SimpleImputer
的输出从二维转换为一维,然后再传递给 CountVectorizer
。
这是完整的代码:
import pandas as pdimport numpy as npdf = pd.DataFrame({'text':['abc def', 'abc ghi', np.nan]})from sklearn.impute import SimpleImputerimp = SimpleImputer(strategy='constant')from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer()# 创建转换器from sklearn.preprocessing import FunctionTransformerone_dim = FunctionTransformer(np.reshape, kw_args={'newshape':-1})# 在 Pipeline 中包含转换器from sklearn.pipeline import make_pipelinepipe = make_pipeline(imp, one_dim, vect)pipe.fit_transform(df[['text']]).toarray()
在 GitHub 上提出,只要第二维度为 1(意味着:单列数据),CountVectorizer
就应该允许二维输入。对 CountVectorizer
的这种修改将是解决此问题的绝佳方案!