假设我有一个包含(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
。
答案 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()
生成实数向量来维护计数器并为同一个索引/插入所需的多个元素丢弃缺失指数的“默认”元素数量。
希望这很清楚。