我正在尝试在我的数据库上运行MLlib算法之一,即LogisticRegressionWithLBFGS。
此算法将训练集作为LabeledPoint。由于LabeledPoint需要双标签(LabeledPoint(双标签,矢量要素))并且我的数据库包含一些空值,我该如何解决这个问题?
在这里,您可以看到与此问题相关的代码:
val labeled = table.map{ row =>
var s = row.toSeq.toArray
s = s.map(el => if (el != null) el.toString.toDouble)
LabeledPoint(row(0), Vectors.dense((s.take(0) ++ s.drop(1))))
}
我得到的错误:
error : type mismatch;
found : Any
required: Double
如果不使用LabeledPoint,我可以运行此算法,或者如何克服这个“空值”问题?
答案 0 :(得分:2)
此代码无法使用的一些原因:
Row.toSeq
的类型为() => Seq[Any]
,因此s
el => if (el != null) el.toString.toDouble
属于T => AnyVal
类型(其中T
为任意)。如果el
为null
,则会返回Unit
var
类型的Seq[Any]
,这正是您所获得的。不管怎样,它都不是Vectors.dense
Row.apply
的类型为Int => Any
,因此输出不能用作标签应该有效但不起作用:
s.take(0)
可能会停止在Spark 2.0中工作
map
超过DataFrame
- 由于Vector
类没有可用的编码器,我们现在无能为力。如何处理此问题:
过滤完整行或填充缺失值,例如使用DataFrameNaFunctions
:
// You definitely want something smarter than that
val fixed = df.na.fill(0.0)
// or
val filtered = df.na.drop
使用VectorAssembler
构建向量:
import org.apache.spark.ml.feature.VectorAssembler
val assembler = new VectorAssembler()
.setInputCols(df.columns.tail)
.setOutputCol("features")
val assembled = assembler.transform(fixed)
转换为LabledPoint
import org.apache.spark.mllib.regression.LabeledPoint
// Assuming lable column is called label
assembled.select($"label", $"features").rdd.map {
case Row(label: Double, features: Vector) =>
LabeledPoint(label, features)
}