2017-04-05 52 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

聽起來不錯!非常感謝!!!! –