Spark数据帧为稀疏向量,为空

时间:2017-04-05 08:26:21

标签: scala apache-spark apache-spark-mllib

当我尝试在scala中组装数据框(某些列包含null值)的向量时,我遇到了问题。很遗憾,vectorAssembler无法处理null值。

我可以做的是替换或填充数据框的null值,然后创建dense向量,但这不是我想要的。

所以我考虑将数据帧行转换为sparse向量。但是我怎么能做到这一点呢?我没有找到vectorAssembler制作稀疏向量的选项。

编辑:实际上我在稀疏向量中不需要null,但它不应该像0或其他任何其他值,因为密集向量就是这种情况。

你有什么建议吗?

1 个答案:

答案 0 :(得分:1)

你可以像这样手动完成:

import org.apache.spark.SparkException
import org.apache.spark.ml.linalg.{Vector, Vectors}
import org.apache.spark.sql.SparkSession
import scala.collection.mutable.ArrayBuilder

case class Row(a: Double, b: Option[Double], c: Double, d: Vector, e: Double)

val dataset = spark.createDataFrame(
  Seq(new Row(0, None, 3.0, Vectors.dense(4.0, 5.0, 0.5), 7.0),
    new Row(1, Some(2.0), 3.0, Vectors.dense(4.0, 5.0, 0.5), 7.0))
).toDF("id", "hour", "mobile", "userFeatures", "clicked")

val sparseVectorRDD = dataset.rdd.map { row =>
  val indices = ArrayBuilder.make[Int]
  val values = ArrayBuilder.make[Double]
  var cur = 0
  row.toSeq.foreach {
    case v: Double =>
      indices += cur
      values += v
      cur += 1
    case vec: Vector =>
      vec.foreachActive { case (i, v) =>
        indices += cur + i
        values += v
      }
      cur += vec.size
    case null =>
      cur += 1
    case o =>
      throw new SparkException(s"$o of type ${o.getClass.getName} is not supported.")
  }
  Vectors.sparse(cur, indices.result(), values.result())
}

然后根据需要将其转换回数据帧。由于Row对象未经过类型检查,因此您必须手动处理它并在需要时强制转换为适当的类型。