我使用Spark 2.0 ,并希望在DataFrame中更新/合并行值。
我有两个DataFrames(旧的和新的),我想以一种方式合并,当旧的DataFrame有比新的DataFrame更多的行时,设置旧的数据值0。
旧数据框:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bc|
## +---+----+----+
新数据框:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bb|
## | 3| cc| cc|
## +---+----+----+
结果:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bb|
## | 3| cc| cc|
## +---+----+----+
旧数据框:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bb|
## | 3| cc| cc|
## +---+----+----+
新数据框:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bc|
## +---+----+----+
结果:
## +---+----+----+
## |key|val1|val2|
## +---+----+----+
## | 1| aa| ab|
## | 2| bb| bc|
## | 3| 00| 00|
## +---+----+----+
密钥在两种情况下是唯一的,在实际情况下,DataFrame可以有很多列。
如何编写Spark / Scala代码以在一个函数中实现这两种情况?
答案 0 :(得分:4)
诀窍是使用fullOuterJoin
和when
条件。
import org.apache.spark.sql.functions._
val dfa = Seq(
(1, "aa", "ab"),
(2, "bb", "bb"),
(3, "cc", "cc")).toDF("key", "val1", "val2")
val dfb = Seq(
(1, "aa", "ab"),
(2, "bb", "bb")).toDF("key", "val1", "val2")
val q = dfa
.join(dfb, Seq("key"), "outer")
.select($"key",
when(dfb("val1").isNull, lit(0)).otherwise(dfb("val1")).as("val1"),
when(dfb("val2").isNull, lit(0)).otherwise(dfb("val2")).as("val2"))
.orderBy("key")
scala> q.show
+---+----+----+
|key|val1|val2|
+---+----+----+
| 1| aa| ab|
| 2| bb| bb|
| 3| 0| 0|
+---+----+----+
答案 1 :(得分:1)
就像the comment中建议的@summerbulb一样,您应该使用na
运算符来填充缺失值。
请注意,我使用as
运算符来为列提供别名。
val oldDF = Seq(
(1, "aa", "ab"),
(2, "bb", "bb"),
(3, "cc", "cc")).toDF("key", "val1", "val2")
val newDF = Seq(
(1, "aa", "ab"),
(2, "bb", "bc")).toDF("key", "val1", "val2")
val q = oldDF.join(newDF.as("new"), Seq("key"), "outer")
.select("key", "new.*")
.na.fill("0") // <-- na.fill("0") because of String type
.orderBy("key")
scala> q.show
+---+----+----+
|key|val1|val2|
+---+----+----+
| 1| aa| ab|
| 2| bb| bc|
| 3| 0| 0|
+---+----+----+
根据列的类型,您可能希望将0
用作String
或Double
类型。
在the scaladoc of Dataset中阅读as
和na
。