2017-04-05 109 views
1

我面临一个问题,当我尝试组装一个矢量形式的数据帧(一些列包含null值)在斯卡拉。不幸的是vectorAssembler无法处理null值。火星数据帧稀疏向量与零

我能做的是替换或填充数据框的值,然后创建一个dense矢量,但这不是我想要的。

所以我想到了将我的数据帧行转换为sparse向量。但是我怎么能实现这个?我还没有找到vectorAssembler的选项来创建一个稀疏矢量。

编辑:其实我不需要null稀疏向量,但它不应该是像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对象未经过类型检查,因此必须手动处理并根据需要转换为适当的类型。

+0

听起来不错!非常感谢!!!! –