Spark DataFrame使用CountVectorizerModel时String类型不匹配错误
问题根因
你对报错的判断准确,CountVectorizerModel 要求输入列类型为 Array[String](字符串数组),而你传入的 ocean_proximity 是普通单值字符串类型,因此触发了类型校验失败。
修复方案
方法1:适配CountVectorizerModel的最小修改方案
只需要提前把单值字符串列转换为单元素字符串数组即可,修改代码如下:
首先引入数组构造函数:
import org.apache.spark.sql.functions.array
调整转换逻辑:
// 将单String列包装为单元素数组列 val dfWithArrayCol = dfRaw.withColumn("ocean_proximity_arr", array(col("ocean_proximity"))) val cvmDF = new CountVectorizerModel(tags) .setInputCol("ocean_proximity_arr") // 改用转换后的数组列作为输入 .setOutputCol("sparseFeatures") .transform(dfWithArrayCol)
注意:你后续生成列别名的写法存在错误,s"$distinctOceanProximities(i)" 会把整个数组转为字符串后拼接(i)后缀,需要修改为 ${distinctOceanProximities(i)} 才能正确取对应下标的分类值作为列名。
方法2:更适配单值分类列的推荐方案
你的需求是对单值分类列做独热编码后转稠密向量,用 StringIndexer + OneHotEncoder 的组合比CountVectorizer更适配该场景,不需要提前收集全量分类值、也不需要手动构造CountVectorizerModel的tags参数,代码更稳定:
import org.apache.spark.ml.feature.StringIndexer import org.apache.spark.ml.feature.OneHotEncoder import org.apache.spark.ml.linalg.Vector import org.apache.spark.sql.functions.udf // 1. 字符串分类值映射为数值索引 val indexer = new StringIndexer() .setInputCol("ocean_proximity") .setOutputCol("ocean_proximity_idx") .fit(dfRaw) // 2. 数值索引转为独热稀疏向量 val encoder = new OneHotEncoder() .setInputCol("ocean_proximity_idx") .setOutputCol("sparseFeatures") .setDropLast(false) // 保留所有分类维度,不会丢弃最后一类 // 3. 稀疏向量转数组 val vecToArray = udf((v: Vector) => v.toArray) val distinctVals = indexer.labels // 直接取训练好的分类标签,顺序和独热向量维度一一对应 // 4. 执行转换拆分多列 val dfTransformed = encoder.transform(indexer.transform(dfRaw)) .withColumn("features_arr", vecToArray(col("sparseFeatures"))) val exprs = (0 until distinctVals.length).map(i => col("features_arr")(i).alias(distinctVals(i))) val finalDF = dfTransformed.select(exprs:_*) finalDF.show()
内容的提问来源于stack exchange,提问作者joesan
相关产品推荐
相关产品推荐

