Scala 如何为RDD2中的每个键替换RDD1中的值?
这里有两个RDD 表1对(键、值) 表2阵列Scala 如何为RDD2中的每个键替换RDD1中的值?,scala,apache-spark,Scala,Apache Spark,这里有两个RDD 表1对(键、值) 表2阵列 val table2 = sc.parallelize(Array(Array("1", "2", "d"), Array("1", "3", "e"))) //RDD[Array[String]] 我试图使用表1中的键和值将表2的元素(如“1”)更改为“a”。我的预期结果如下: RDD[Array[String]] = (Array(Array("a", "b", "d"), Array("a", "c", "e"))) 有没有办法让这成
val table2 = sc.parallelize(Array(Array("1", "2", "d"), Array("1", "3", "e")))
//RDD[Array[String]]
我试图使用表1中的键和值将表2的元素(如“1”)更改为“a”。我的预期结果如下:
RDD[Array[String]] = (Array(Array("a", "b", "d"), Array("a", "c", "e")))
有没有办法让这成为可能
如果是这样的话,使用一个庞大的数据集是否有效
有没有办法让这成为可能
对。使用数据集(而不是RDD),将它们连接在一起,然后选择您喜欢的字段
val table1 = Seq(("1", "a"), ("2", "b"), ("3", "c")).toDF("key", "value")
scala> table1.show
+---+-----+
|key|value|
+---+-----+
| 1| a|
| 2| b|
| 3| c|
+---+-----+
val table2 = sc.parallelize(
Array(Array("1", "2", "d"), Array("1", "3", "e"))).
toDF("a").
select($"a"(0) as "a0", $"a"(1) as "a1", $"a"(2) as "a2")
scala> table2.show
+---+---+---+
| a0| a1| a2|
+---+---+---+
| 1| 2| d|
| 1| 3| e|
+---+---+---+
scala> table2.join(table1, $"key" === $"a0").select($"value" as "a0", $"a1", $"a2").show
+---+---+---+
| a0| a1| a2|
+---+---+---+
| a| 2| d|
| a| 3| e|
+---+---+---+
对其他a
列和union
一起重复上述操作。在重复代码时,您会注意到使代码通用的模式
如果是这样的话,使用一个庞大的数据集是否有效
是的(再次)。我们这里说的是Spark,一个庞大的数据集正是您选择Spark的原因,不是吗?您可以在数据集中这样做
package dataframe
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.{SQLContext, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}
/**
* @author vaquar.khan@gmail.com
*/
object Test {
case class table1Class(key: String, value: String)
case class table2Class(key: String, value: String, value1: String)
def main(args: Array[String]) {
val spark =
SparkSession.builder()
.appName("DataFrame-Basic")
.master("local[4]")
.getOrCreate()
import spark.implicits._
//
val table1 = Seq(
table1Class("1", "a"), table1Class("2", "b"), table1Class("3", "c"))
val df1 = spark.sparkContext.parallelize(table1, 4).toDF()
df1.show()
val table2 = Seq(
table2Class("1", "2", "d"), table2Class("1", "3", "e"))
val df2 = spark.sparkContext.parallelize(table2, 4).toDF()
df2.show()
//
df1.createOrReplaceTempView("A")
df2.createOrReplaceTempView("B")
spark.sql("select d1.key,d1.value,d2.value1 from A d1 inner join B d2 on d1.key = d2.key").show()
//TODO
/* need to fix query
spark.sql( "select * from ( "+ //B1.value,B1.value1,A.value
" select A.value,B.value,B.value1 "+
" from B "+
" left join A "+
" on B.key = A.key ) B2 "+
" left join A " +
" on B2.value = A.key" ).show()
*/
}
}
结果:
+---+-----+
|key|value|
+---+-----+
| 1| a|
| 2| b|
| 3| c|
+---+-----+
+---+-----+------+
|key|value|value1|
+---+-----+------+
| 1| 2| d|
| 1| 3| e|
+---+-----+------+
[Stage 15:=====================================> (68 + 6) / 100]
[Stage 15:============================================> (80 + 4) / 100]
+-----+-----+------+
|value|value|value1|
+-----+-----+------+
| 1| a| d|
| 1| a| e|
+-----+-----+------+
我认为我们可以在避免连接的同时更好地使用数据帧,因为它可能涉及数据的洗牌
val table1 = spark.sparkContext.parallelize(Seq(("1", "a"), ("2", "b"), ("3", "c"))).collectAsMap()
//Brodcasting so that mapping is available to all nodes
val brodcastedMapping = spark.sparkContext.broadcast(table1)
val table2 = spark.sparkContext.parallelize(Array(Array("1", "2", "d"), Array("1", "3", "e")))
def changeMapping(value: String): String = {
brodcastedMapping.value.getOrElse(value, value)
}
val changeMappingUDF = udf(changeMapping(_:String))
table2.toDF.withColumn("exploded", explode($"value"))
.withColumn("new", changeMappingUDF($"exploded"))
.groupBy("value")
.agg(collect_list("new").as("mappedCol"))
.select("mappedCol").rdd.map(r => r.toSeq.toArray.map(_.toString))
让我知道它是否适合您的要求,否则我可以根据需要修改它。OP询问RDD,所以如果您需要,答案应该是关于RDD和数据集的。RDD也有join,但只有PariRDD@T.Gawęda OP询问了他们所知道的事情。“我更愿意分享Spark的好处,而不是直接回答可能导致代码效率低下且难以维护的问题。”JacekLaskowski是的,现在他告诉我们。但问题是(现在也是)关于RDD。回答得好,我也会推荐数据集,但在谈到API之前,OP会询问,谢谢您的回复。仅使用
RDD
而不是DataFrame
是否无法解决此问题?明白。谢谢你的回复。好的。但我更愿意为table1
使用广播表,并去掉UDF(因为它会因为SerDe而导致性能损失)。谢谢你这么好的主意!向上投票!谢谢你的回复。用RDD
而不是DataFrame
解决这个问题没有办法吗?bump for RDD only solution,为什么这是一个一般性的问题?顺便说一句,这个问题应该被固定为“具有很好示例的问题”。用于数据和可视化的开箱即用脚本:)感谢您的回复。是否无法仅使用RDD
而不是DataFrame
来解决此问题?
val table1 = spark.sparkContext.parallelize(Seq(("1", "a"), ("2", "b"), ("3", "c"))).collectAsMap()
//Brodcasting so that mapping is available to all nodes
val brodcastedMapping = spark.sparkContext.broadcast(table1)
val table2 = spark.sparkContext.parallelize(Array(Array("1", "2", "d"), Array("1", "3", "e")))
def changeMapping(value: String): String = {
brodcastedMapping.value.getOrElse(value, value)
}
val changeMappingUDF = udf(changeMapping(_:String))
table2.toDF.withColumn("exploded", explode($"value"))
.withColumn("new", changeMappingUDF($"exploded"))
.groupBy("value")
.agg(collect_list("new").as("mappedCol"))
.select("mappedCol").rdd.map(r => r.toSeq.toArray.map(_.toString))