在使用OneHotEncoder时,对编码后的结果,Spark都追加在了一列Vector列,而我们的需求是要把扩展的这些列横向展开为多维度,而不是在一个矩阵列里。
我们的思路是将vector列通过自定义udf转化为array列,再通过zipWithIndex操作获取array下标横向扩展,下面是代码:
//一次性转换所有向量列
val vecToArrExprs: Array[Column] = transCols.map(colName => {
//vector列名
val vectorColName = colName + "_indexed_encoded"
vecToArray($"$vectorColName").alias(colName + "_arr_tmp")
})
val orginalCols = inputDF.schema.fieldNames.map(colName => $"$colName")
//将vector转为arr后的dataframe
val transArrDF = oneHotDF.select((orginalCols ++ vecToArrExprs): _*)
//一次性扩展所有arr列
val extendExprs: Array[Column] = transCols.flatMap(colName => {
//arr列名
val arrColName = colName + "_arr_tmp"
//获取每列的扩展字段名数组
val newColNameArr = colValueCountMap.get(colName).get.toArray.sortBy(_._2).reverse.map(colName + "_if_" + _._1)
newColNameArr.zipWithIndex.map { case (newColName, index) => {
$"$arrColName".getItem(index).alias(newColName)
}
}
})
//扩展后的最终的dataframe
val finalDF = transArrDF.select((orginalCols ++ extendExprs): _*)