我正在尝试在我的数据库上运行MLlib算法之一,即LogisticRegressionWithLBFGS。
此算法将训练集作为标记点。由于 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 是否可以运行此算法,或者如何克服此"空值"问题?
此代码无法工作的一些原因:
-
Row.toSeq
属于() => Seq[Any]
类型,s
- 由于您只涵盖非空情况
el => if (el != null) el.toString.toDouble
因此属于T => AnyVal
类型(其中T
是任何)。如果el
null
则返回Unit
- 即使不是你把它分配给
Seq[Any]
类型的var
,这正是你得到的。无论如何,它不是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) }