将[(Int,Seq [Double])] RDD转换为LabeledPoint

时间:2016-03-14 11:42:21

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

我有一个以下格式的RDD,并希望将其转换为LabeledPoint RDD,以便在mllib中处理它:

Test: RDD[(Int, Seq[Double])] = Array((1,List(1.0,3.0,8.0),(2,List(3.0, 3.0,8.0),(1,List(2.0,3.0,7.0),(1,List(5.0,5.0,9.0))

我尝试使用地图

import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.regression.LabeledPoint
Test.map(x=> LabeledPoint(x._1, Vectors.sparse(x._2)))

但我收到此错误

mllib.linalg.Vector cannot be applied to (Seq[scala.Double])

所以推测Seq元素需要先转换,但我不知道是什么。

2 个答案:

答案 0 :(得分:1)

这里有一些问题:

  • 标签应为Double而不是Int
  • SparseVector需要多少元素,索引和值
  • 没有任何矢量构造函数接受Double
  • 的列表
  • 您的数据看起来密集而不稀疏

一种可能的解决方案:

val rdd = sc.parallelize(Array(
    (1, List(1.0,3.0,8.0)),
    (2, List(3.0, 3.0,8.0)),
    (1, List(2.0,3.0,7.0)),
    (1, List(5.0,5.0,9.0))))

rdd.map { case (k, vs) => 
  LabeledPoint(k.toDouble, Vectors.dense(vs.toArray))
}

和另一个:

rdd.collect { case (k, v::vs) =>
  LabeledPoint(k.toDouble, Vectors.dense(v, vs: _*)) }

答案 1 :(得分:1)

正如您在LabeledPoint's documentation中所注意到的那样,其构造函数会收到Double作为标签,Vector作为要素(DenseVectorSparseVector)。但是,如果您查看两个继承类的构造函数,则会收到Array,因此您需要将Seq转换为Array

import org.apache.spark.mllib.linalg.{Vector, Vectors, DenseVector}
import org.apache.spark.mllib.regression.LabeledPoint

val rdd = sc.parallelize(Array((1, Seq(1.0,3.0,8.0)), 
                               (2, Seq(3.0, 3.0,8.0)),
                               (1, Seq(2.0,3.0, 7.0)),
                               (1, Seq(5.0, 5.0, 9.0))))
val x = rdd.map{
    case (a: Int, b:Seq[Double]) => LabeledPoint(a, new DenseVector(b.toArray))
}

x.take(2).foreach(println)

//(1.0,[1.0,3.0,8.0])
//(2.0,[3.0,3.0,8.0])
相关问题