如何避免使用Spark进行循环?

时间:2015-04-17 11:38:54

标签: scala for-loop apache-spark

我是新手,并且不了解mapreduce机制如何与spark一起使用。我有一个只有双打的csv文件,我想要的是用第一个向量与rdd的其余部分进行操作(计算欧几里德距离)。然后用其他向量迭代。它存在于另一种方式吗?也许明智地使用笛卡尔积......

val rdd = sc.parallelize(Array((1,Vectors.dense(1,2)),(2,Vectors.dense(3,4),...)))
val array_vects = rdd.collect
val size = rdd.count
val emptyArray = Array((0,Vectors.dense(0))).tail
var rdd_rez = sc.parallelize(emptyArray)

for( ind <- 0 to size -1 ) {
   val vector = array_vects(ind)._2
   val rest = rdd.filter(x => x._1 != ind)
   val rdd_dist = rest.map( x => (x._1 , Vectors.sqdist(x._2,vector)))
   rdd_rez = rdd_rez ++ rdd_dist
}

感谢您的支持。

2 个答案:

答案 0 :(得分:4)

可以使用rdd.cartesian

计算距离(所有矢量对之间)
val rdd = sc.parallelize(Array((1,Vectors.dense(1,2)),
                               (2,Vectors.dense(3,4)),...))
val product = rdd.cartesian(rdd)

val result = product.filter{ case ((a, b), (c, d)) => a != c }
                    .map   { case ((a, b), (c, d)) => 
                                   (a, Vectors.sqdist(b, d)) }

答案 1 :(得分:0)

我不会想到你为什么要这样做。您可以按照以下方式执行此操作。

val initialArray = Array( ( 1,Vectors.dense(1,2) ), ( 2,Vectors.dense(3,4) ),... )

val firstVector = initialArray( 0 )

val initialRdd = sc.parallelize( initialArray )

val euclideanRdd = initialRdd.map( { case ( i, vec ) => ( i, euclidean( firstVector, vec ) ) } )

我们定义一个函数euclidean,它取两个密集向量并返回欧氏距离。