【问题标题】:Tried/failed to replace null values with means in spark dataframe尝试/未能用火花数据框中的手段替换空值
【发布时间】:2017-09-14 12:45:00
【问题描述】:

更新:我错了,错误源于向量汇编器,而不是随机森林,或者两者都来自。但是错误/问题是一样的。当我在 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 现在应该是只有没有空值的数字列的数据框,它们已被替换为空列。然而,当尝试制作所有值的向量(减去标签/目标)时,我得到“要组装的值不能为空”错误。我附上了错误的屏幕截图,以防万一。它还说它无法执行用户定义的功能。

我知道我最近在这里问了很多关于 scala 的问题,对此很抱歉,我只是真的在努力学习如何做到这一点。以下是 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)

【问题讨论】:

  • 您的代码似乎按预期工作 - 也许问题出在其他地方?也许以您“创建[e]所有值的向量(减去标签/目标)”的方式?
  • 我添加了其余代码和错误消息以防万一

标签: scala apache-spark


【解决方案1】:

猜测这是一个完全为空的列 - 在这种情况下,平均值也会为空。为避免这种情况,您可以简单地在 coalesce 表达式中添加另一个“后备”,例如使用文字 0:

val exprs = numDf.columns.map(c => coalesce(col(c), col(s"avg($c)"), lit(0.0)).alias(c))

在其余代码不变的情况下,这应确保df_noNulls 中的所有值都不为空。

【讨论】:

  • 我觉得自己像个白痴。你是对的。我知道这是另一个问题,但现在我的任务是找到让 scala 返回一个数组、列表等具有所有值都为空的列名的最佳方法。我确实 describe() 并且我没有看到该列的计数为 0,因为它被埋在 500 奇数列的中间。非常感谢!
猜你喜欢
  • 2022-01-08
  • 1970-01-01
  • 2022-08-05
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多