更新:我错了,错误来自vectorassembler,而不是随机森林,或来自两者。但错误/问题是一样的。当我在vectorAssembler中使用df_noNulls数据帧时,它表示它无法对列进行矢量化,因为它有空值。
我已经查看了这个问题的其他答案,并解放/借用/窃取了答案代码,试图让它发挥作用。我的最终目标是RF / GB /其他ML建模,它不会对空值感兴趣。我将以下代码放在一起以拉出所有数字列,得到每个列的意思,然后创建一个新的数据框,连接两个并用平均值替换所有空值。然后,当我尝试创建数字列的向量作为"功能"作为随机森林的一部分,它返回一个错误,表示"汇编的值不能为空"。
val numCols = DF.schema.fields filter {
x => x.dataType match {
case x: org.apache.spark.sql.types.DoubleType => true
case x: org.apache.spark.sql.types.IntegerType => true
case x: org.apache.spark.sql.types.LongType => true
case _ => false
}
} map {x => x.name}
//NUMCOLS NOW IS AN ARRAY OF ALL NUMERIC COLUMN NAMES
val numDf = DF.select(numCols.map(col): _*)
//NUMDF IS A DATAFRAME OF ALL NUMERIC COLUMNS
val means = numDf.agg(numDf.columns.map(c => (c -> "avg")).toMap)
//CREATES A DATAFRAME OF MEANS OF ALL NUMERIC VARIABLES
means.persist()
//PERSIST TABLE 'MEANS' FOR JOINING --BROADCAST ALSO WORKS BUT I WAS GETTING MEMORY ISSUES WITH IT SO I SWITCHED IT
val exprs = numDf.columns.map(c => coalesce(col(c), col(s"avg($c)")).alias(c))
//EXPRS CREATES FUNCTION TO REPLACE NULLS WITH MEANS
val df_noNulls = DF.crossJoin(means).select(exprs: _*)
df_noNulls现在应该只是没有空值的数字列的数据框,它们已被列空值替换。然而,当试图制作所有值的矢量(减去标签/目标)时,我得到了#34;汇编的值不能为空"错误。我附上了错误的屏幕截图,以防可能有所帮助。它还说它无法执行用户定义的函数。
我知道我最近在这里问了很多关于斯卡拉的问题,对不起,我真的很想学会这么做。下面是RF步骤的其余代码,以防错误出现在某处:
val num_feat = numCols.filter(! _.contains("call"))
val features=num_feat
val featureAssembler = new VectorAssembler().setInputCols(features).setOutputCol("features")
val reweight_vector = featureAssembler.transform(df_noNulls)
val rf50 = new RandomForestClassifier().setSeed(9).setLabelCol("call_ind").setFeaturesCol("features").setNumTrees(500).setMaxBins(100).fit(reweight_vector)
答案 0 :(得分:1)
我猜测原因是列完全为空 - 在这种情况下,平均值也将为null。为避免这种情况,您只需添加另一个"后备"在coalesce
表达式中,使用文字0,例如:
val exprs = numDf.columns.map(c => coalesce(col(c), col(s"avg($c)"), lit(0.0)).alias(c))
如果将其余代码解除连接,则应确保df_noNulls
中的所有值都不为空。