我有这个文件,其中包含三种类型的数据,如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
答案 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)