替换RDD的一些元素

时间:2016-02-11 04:26:12

标签: scala apache-spark rdd

我有这个文件,其中包含三种类型的数据,如A,B,C。我想基于某些条件,仅将此RDD的Type A元素(称为RDD1)替换为其他RDD的元素(称为RDD2).RDD1和RDD2有一些共同的字符串。

文件结构[RDD [String]]

1 A 2   
2 B 12 13 4
2 C 67 29  
2 A 5

RDD2 [RDD [Row]]

1 A 2 5 6
2 A 5 7 8 

我正在过滤第一个RDD并为其添加一些字符串以创建RDD2。

我知道RDD是不可变的,但由于地图功能不参与。我想知道是否有办法实现这一点。

编辑:考虑以下评论

示例输出RDD [Any]

1 A 2 5 6
2 B 12 13 4
2 C 67 29
2 A 5 7 8

2 个答案:

答案 0 :(得分:2)

您应该考虑在RDD中使用更合适和明确的数据结构,例如(密钥,值)对的RDD。

然后,您可以利用密钥在RDD1和RDD2之间执行连接" a la SQL"。我相信这是Gabber上面已经做过的事情,但是使用了Scala语法糖的全部功能。

以更明确的方式: 您的初始RDD,如Gabber

val rdd1 = sc.parallelize(Seq(List("1", "A", "2"), List("2", "B", "12", "13", "4"), List("2", "C", "67", "29"), List("2", "A", "5")))
val rdd2 = sc.parallelize(Seq(List("1", "A", "2", "5", "6"), List("2", "A", "5", "7", "8")))

然后使用地图创建一个(键,值)对的RDD,其中该键将用于满足您的匹配条件(您的密钥似乎在您的示例中是前两个元素(。,A))

val rdd1KeyValue = rdd1.map(row => ((row(0),row(1)), row)
val rdd2KeyValue = rdd2.map(row => ((row(0),row(1)), row))

现在,因为你想要执行"加入"使用Key" A"并留下其他非匹配,这是一个SQL左外连接。所以:

val resultRaw = rdd1KeyValue.leftOuterJoin(rdd2KeyValue)

但是resultRaw现在是这样的:

((2,C),(List(2, C, 67, 29),None))
((1,A),(List(1, A, 2),Some(List(1, A, 2, 5, 6))))
((2,B),(List(2, B, 12, 13, 4),None))
((2,A),(List(2, A, 5),Some(List(2, A, 5, 7, 8))))

因此,要获得最终结果,您需要再次映射到"选择"你需要什么(._1运算符是取一个(键,值)对的第一个值):

val resFinal = result.map(row => row._2._2.getOrElse(row._2._1))

就我而言,最终结果是:

List(1, A, 2, 5, 6)
List(2, B, 12, 13, 4)
List(2, A, 5, 7, 8)
List(2, C, 67, 29)

答案 1 :(得分:0)

它为我工作

val rdd1 = sc.parallelize(Seq(List("1", "A", "2"), List("2", "B", "12", "13", "4"), List("2", "C", "67", "29"), List("2", "A", "5")))
val rdd2 = sc.parallelize(Seq(List("1", "A", "2", "5", "6"), List("2", "A", "5", "7", "8")))
rdd1.map(row =>//where row(0), row(1) is your condition
  ((row(0), row(1)), row)).leftOuterJoin(rdd2.map(row =>
  ((row(0), row(1)), row))).map(row => {
  row._2._2.getOrElse(row._2._1)
}).foreach(println)