如何通过key或filter()使用两个RDD的spark intersection()?

时间:2017-02-19 09:16:52

标签: scala apache-spark filter rdd intersection

我希望按键使用intersection()或在spark中使用filter()

但我真的不知道如何按键使用intersection()

所以我尝试使用filter(),但它没有用。

示例 - 这是两个RDD:

data1 //RDD[(String, Int)] = Array(("a", 1), ("a", 2), ("b", 2), ("b", 3), ("c", 1))
data2 //RDD[(String, Int)] = Array(("a", 3), ("b", 5))

val data3 = data2.map{_._1}

data1.filter{_._1 == data3}.collect //Array[(String, Int] = Array()

我希望根据data1所拥有的密钥,使用与data2相同的密钥获取(密钥,值)对。

Array(("a", 1), ("a", 2), ("b", 2), ("b", 3))是我想要的结果。

是否有方法可以使用intersection()按键filter()来解决此问题?

2 个答案:

答案 0 :(得分:6)

对于您的问题,我认为cogroup()更适合您。 intersection()方法会同时考虑数据中的键和值,并会导致空rdd

函数cogroup()按键对rdd的值进行分组,并为我们提供(key, vals1, vals2),其中vals1vals2包含值{每个密钥分别为{1}}和data1。请注意,如果两个数据集中未共享某个键,则data2vals1中的一个将作为空vals2返回,因此我们首先必须将这些元组过滤掉到达两个Seq交叉点

接下来,我们将抓取rdd - 其中包含来自vals1,用于公共 - 并将其转换为格式{ {1}}。最后,我们使用data1将结果解压缩为(key, Array)格式。

flatMapValues()

答案 1 :(得分:1)

  

这可以通过不同的方式实现

1。 broadcast中的filter()变量 - 需要提高可扩展性

val data1 = sc.parallelize(Seq(("a", 1), ("a", 2), ("b", 2), ("b", 3), ("c", 1)))
val data2 = sc.parallelize(Seq(("a", 3), ("b", 5)))

// broadcast data2 key list to use in filter method, which runs in executor nodes
val bcast = sc.broadcast(data2.map(_._1).collect())

val result = data1.filter(r => bcast.value.contains(r._1))


println(result.collect().toList)
//Output
List((a,1), (a,2), (b,2), (b,3))

2。 cogroup(类似于按键分组)

val data1 = sc.parallelize(Seq(("a", 1), ("a", 2), ("b", 2), ("b", 3), ("c", 1)))
val data2 = sc.parallelize(Seq(("a", 3), ("b", 5)))

val cogroupRdd: RDD[(String, (Iterable[Int], Iterable[Int]))] = data1.cogroup(data2)
/* List(
  (a, (CompactBuffer(1, 2), CompactBuffer(3))),
  (b, (CompactBuffer(2, 3), CompactBuffer(5))),
  (c, (CompactBuffer(1), CompactBuffer()))
) */

//Now filter keys which have two non empty CompactBuffer. You can do that with 
//filter(row => row._2._1.nonEmpty && row._2._2.nonEmpty) also. 
val filterRdd = cogroupRdd.filter { case (k, (v1, v2)) => v1.nonEmpty && v2.nonEmpty } 
/* List(
  (a, (CompactBuffer(1, 2), CompactBuffer(3))),
  (b, (CompactBuffer(2, 3), CompactBuffer(5)))
) */

//As we care about first data only, lets pick first compact buffer only 
// by doing v1.map(val1 => (k, val1))
val result = filterRdd.flatMap { case (k, (v1, v2)) => v1.map(val1 => (k, val1)) }
//List((a, 1), (a, 2), (b, 2), (b, 3))

3。使用内连接

val resultRdd = data1.join(data2).map(r => (r._1, r._2._1)).distinct()
//List((b,2), (b,3), (a,2), (a,1)) 

此处data1.join(data2)包含具有公共密钥的对(内部联接

//List((a,(1,3)), (a,(2,3)), (b,(2,5)), (b,(2,1)), (b,(3,5)), (b,(3,1)))