Spark:如何根据RDD

时间:2019-03-05 08:58:37

标签: scala apache-spark pyspark rdd

我有3列(road_idx,snodeidx,enodeidx)的RDD。 看起来像这样:

(roadidx_995, 1138, 1145)
(roadidx_996, 1138, 1139)
(roadidx_997, 2740, 1020)
(roadidx_998, 2762, 2740)
(roadidx_999, 3251, 3240)
.........

如何将具有共同的snodeidx或enodeidx之一的road_idx组合在一起?给每个组一个从1开始的数字。

预期输出:

(1,[roadidx_995,roadidx_996])
(2,[roadidx_997,roadidx_998])
(3,[roadidx_999])

如上所示,

roadidx_995和roadidx_996具有相同的 snodeidx 1138。

roadidx_997的 snodeidx 与roadidx_998的 enodeidx 相同,为2740。

roadidx_999单独位于一个组中。

Scala代码或Python代码都可以。只要您能告诉我使用RDD API获得预期输出的逻辑即可。

非常感谢!

1 个答案:

答案 0 :(得分:-1)

可以实现为:

  1. 在两个rdd上分割原稿-按“开始”和“结束”节点分组。
  2. 多次使用1)中的值加入原始数据集,并获得四列,如:

    checkbox
  3. 将四列中的值一并加入

在Scala上可以实现:

|------------------|----------------|--------------|----------------|
| start join start | start join end | end join end | end join start |
|------------------|----------------|--------------|----------------|

输出为:

val data = List(
  ("roadidx_995", 1138, 1145),
  ("roadidx_996", 1138, 1139),
  ("roadidx_997", 2740, 1020),
  ("roadidx_998", 2762, 2740),
  ("roadidx_999", 3251, 3240)
)
val original = sparkContext.parallelize(data)

val groupedByStart = original.map(v => (v._1, v._2)).groupBy(_._2).mapValues(_.map(_._1))
val groupedByEnd = original.map(v => (v._1, v._3)).groupBy(_._2).mapValues(_.map(_._1))
val indexesOnly = original.map(allRow => (allRow._2, allRow._3))

// join by start value
val startJoinsStart = indexesOnly.keyBy(_._1).join(groupedByStart)
val startJoinsEnd = startJoinsStart.leftOuterJoin(groupedByEnd)

// join by end value
val endKeys = startJoinsEnd.values.keyBy(_._1._1._2)

val endJoinsEnd = endKeys.join(groupedByEnd)
val endJoinsStart = endJoinsEnd.leftOuterJoin(groupedByStart)

// flatten to output format
val result = endJoinsStart
  .values
  .map(v => (v._1._1._1._2, v._1._1._2, v._1._2, v._2))
  .map(v => v._1 ++ v._2.getOrElse(Seq()) ++ v._3 ++ v._4.getOrElse(Seq()))
  .map(_.toSet)
  .distinct()

result.foreach(println)