如何将RDD [Row]转换为RDD [Vector]

时间:2016-05-27 16:52:11

标签: scala apache-spark-mllib

我正在尝试使用scala实现k-means方法。 我创建了类似的RDD

val df = sc.parallelize(data).groupByKey().collect().map((chunk)=> {
  sc.parallelize(chunk._2.toSeq).toDF()
})

val examples = df.map(dataframe =>{
  dataframe.selectExpr(
    "avg(time) as avg_time",
    "variance(size) as var_size",
    "variance(time) as var_time",
    "count(size) as examples"
  ).rdd
})

val rdd_final=examples.reduce(_ union _)

val kmeans= new KMeans()
val model = kmeans.run(rdd_final)

使用此代码我会收到错误

type mismatch;
[error]  found   : org.apache.spark.rdd.RDD[org.apache.spark.sql.Row]
[error]  required:org.apache.spark.rdd.RDD[org.apache.spark.mllib.linalg.Vector]

所以我试着去做:

val rdd_final_Vector = rdd_final.map{x:Row => x.getAs[org.apache.spark.mllib.linalg.Vector](0)}

val model = kmeans.run(rdd_final_Vector)

但后来我得到了一个错误:

java.lang.ClassCastException: java.lang.Double cannot be cast to org.apache.spark.mllib.linalg.Vector

所以我正在寻找一种方法来进行演员表,但我找不到任何方法。

有什么想法吗?

祝你好运

1 个答案:

答案 0 :(得分:1)

至少有几个问题:

  1. 你真的无法将一行投射到一个矢量:一行是Spark SQL理解的潜在不同类型的集合。 Vector不是本机spark sql类型
  2. SQL语句的内容与使用KMeans尝试实现的内容之间似乎不匹配:SQL正在执行聚合。但是KMeans期望一个单独的数据点形式为Vector(它封装了Array[Double])。那么 - 为什么要将sumaverage提供给KMeans操作?
  3. 在这里解决#1问题:你需要做一些事情:

    val doubVals = <rows rdd>.map{ row =>   row.getDouble("colname") }
    val vector = Vectors.toDense{ doubVals.collect}
    

    然后你有一个正确封装的Array[Double](在Vector中),可以提供给Kmeans