对每个分区执行Spark crossJoin

时间:2018-07-19 18:34:08

标签: scala apache-spark cartesian-product cross-join

我正在尝试一些自定义距离函数以进行无监督学习,在此我需要将数据集中的每个向量与所有其他向量进行比较。由于我无法从数据框内调用数据框(或从数据框内的rdd或其任何组合)调用-我相信crossJoin是唯一的方法。

很明显,crossJoin触发创建 nxn 数据集的情况,该数据集中有 n 个向量。但是,我可以忍受一次执行一个向量的crossJoin,因为每个向量都是独立评估的。那么,是否有一种方法可以执行crossJoin(不是延迟执行,而是实际计算)和每个分区的后续计算,因此群集实际上不需要评估和存储整个 nxn 矩阵? / p>

编辑:一个用于演示该问题的小例子:

// X and Y are transformed using VectorAssembler to generate the vector V
vdf.show(20,200)
+-------+-------+-----------------+
|      X|      Y|                V|
+-------+-------+-----------------+
|  623.0| 9869.0|   [623.0,9869.0]|
| 5287.0| 9217.0|  [5287.0,9217.0]|
| 9369.0| 4000.0|  [9369.0,4000.0]|
| 3053.0| 7106.0|  [3053.0,7106.0]|
| 7281.0| 7859.0|  [7281.0,7859.0]|
|20000.0|30000.0|[20000.0,30000.0]|
+-------+-------+-----------------+

//Next, we do a crossJoin to create a matrix of nxn
val cv = vdf.select($"V".alias("V1")).crossJoin(vdf.select($"V".alias("V2")))
cv.sort("V1").show(40,200)

cv: org.apache.spark.sql.DataFrame = [V1: vector, V2: vector]
+-----------------+-----------------+
|               V1|               V2|
+-----------------+-----------------+
|   [623.0,9869.0]|   [623.0,9869.0]|
|   [623.0,9869.0]|  [9369.0,4000.0]|
|   [623.0,9869.0]|  [3053.0,7106.0]|
|   [623.0,9869.0]|[20000.0,30000.0]|
|   [623.0,9869.0]|  [5287.0,9217.0]|
|   [623.0,9869.0]|  [7281.0,7859.0]|
|  [3053.0,7106.0]|  [3053.0,7106.0]|
|  [3053.0,7106.0]|   [623.0,9869.0]|
|  [3053.0,7106.0]|  [9369.0,4000.0]|
|  [3053.0,7106.0]|  [5287.0,9217.0]|
|  [3053.0,7106.0]|[20000.0,30000.0]|
|  [3053.0,7106.0]|  [7281.0,7859.0]|
..........
..........

但是,如果我们可以对每个唯一的V1进行crossJoin以及对crossJoined数据集进行后续计算,则可以避免上述情况。之后,可以将结果数据帧的数组或RDD连接起来,以比较每个向量的得分。

我试图通过在crossJoin之前为每个向量分配一个uniqueId,将uniqueIds提取为数组,然后在for / foreach / map循环中执行crossJoin和其他数据帧操作的同时遍历该数组来控制执行,但是看起来就像如果我遍历本地数组一样,它们都将在驱动程序内执行(这令人困惑,因为我以为循环内的数据帧操作将被分发,但显然它们不会被分发)。

我正在将EMR与Spark 2.3.0(Scala 2.11.8)一起使用。

0 个答案:

没有答案