如何将已知的结构化RDD转换为Vector

时间:2014-12-18 21:00:16

标签: scala vector apache-spark distributed-computing rdd

假设我有一个包含(Int,Int)元组的RDD。 我希望把它变成一个Vector,其中元组中的第一个Int是索引,第二个是值。

任何想法我该怎么做?

我更新了我的问题并添加了我的解决方案以澄清: 我的RDD已经被密钥减少了,密钥的数量是已知的。 我想要一个向量来更新单个累加器而不是多个累加器。

我的最终解决方案是:

reducedStream.foreachRDD(rdd => rdd.collect({case (x: Int,y: Int) => {
  val v = Array(0,0,0,0)
  v(x) = y
  accumulator += new Vector(v)
}}))

在文档中使用累加器示例中的Vector

2 个答案:

答案 0 :(得分:4)

rdd.collectAsMap.foldLeft(Vector[Int]()){case (acc, (k,v)) => acc updated (k, v)}

将RDD转换为地图。然后迭代,在我们去的时候构建一个Vector。

你可以使用justt collect(),但是如果有很多重复的元组具有可能不适合内存的相同键。

答案 1 :(得分:3)

一件关键的事情:你真的需要Vector吗?地图可能更合适。

  • 如果你真的需要本地Vector,你首先需要使用.collect()然后在Vector中进行局部转换。当然,你应该有足够的记忆。但这里真正的问题是在哪里找到可以从(索引,值)对有效构建的Vector。据我所知,Spark MLLib有自己的类org.apache.spark.mllib.linalg.Vectors,它可以从索引和值数组创建Vector,甚至可以从元组创建。在引擎盖下它使用breeze.linalg。所以可能最适合你。

  • 如果您只是需要订购,则可以使用.orderByKey(),因为您已经拥有RDD[(K,V)]。这样你就有了订购流。这并不严格遵循你的意图,但也许它可能更适合你。现在,您可以通过.reduceByKey()删除具有相同键的元素,仅生成结果元素。

  • 最后,如果你确实需要大型向量,请执行.orderByKey,然后你可以通过.flatmap()生成实数向量来维护计数器并为同一个索引/插入所需的多个元素丢弃缺失指数的“默认”元素数量。

希望这很清楚。