比较两个数据框中的列值

时间:2018-09-13 06:18:13

标签: scala apache-spark apache-spark-sql compare

我有两个数据框,一个具有唯一值id,另一个可以具有多个不同id的值。

这是数据帧df1

id | dt| speed | stats
358899055773504 2018-07-31 18:38:34 0 [9,-1,-1,13,0,1,0]
358899055773505 2018-07-31 18:48:23 4 [8,-1,0,22,1,1,1]

df2

id | dt| speed | stats
358899055773504 2018-07-31 18:38:34 0 [9,-1,-1,13,0,1,0]
358899055773505 2018-07-31 18:54:23 4 [9,0,0,22,1,1,1]
358899055773504 2018-07-31 18:58:34 0 [9,0,-1,22,0,1,0]
358899055773504 2018-07-31 18:28:34 0 [9,0,-1,22,0,1,0]
358899055773505 2018-07-31 18:38:23 4 [8,-1,0,22,1,1,1]

我的目标是将第二个数据帧与第一个数据帧进行比较,并更新第一个数据帧中的值,除非dt的特定id的{​​{1}}的值大于该值df2中的值,如果满足大于条件,则也比较其他字段。

1 个答案:

答案 0 :(得分:1)

您需要join将两个数据框放在一起以对其列进行任何比较。

您可以做的是先加入数据框,然后执行所有过滤以获取包含所有应更新的所有行的新数据框:

val diffDf = df1.as("a").join(df2.as("b"), Seq("id"))
  .filter($"b.dt" > $"a.dt")
  .filter(...)                                          // Any other filter required
  .select($"id", $"b.dt", $"b.speed", $"b.stats")

注意::在某些情况下,{{1}中每个groupBy(id)仅应有一行最后一行,这可能需要执行id或使用窗口函数1}}数据框。可以按照以下步骤进行操作(此处的示例将选择速度最大的行,但这取决于实际要求):

diffDf

可以在以下位置找到有关不同方法的更多深入信息:How to max value and keep all columns (for max records per group)?


要用val w = Window.partitionBy($"id").orderBy($"speed".desc) val diffDf2 = diffDf.withColumn("rn", row_number.over(w)).where($"rn" === 1).drop("rn") 数据框中的相同id替换旧行,请将数据框与外部联接和df1组合在一起:

coalesce

val df = df1.as("a").join(diffDf.as("b"), Seq("id"), "outer") .select( $"id", coalesce($"b.dt", $"a.dt").as("dt"), coalesce($"b.speed", $"a.speed").as("speed"), coalesce($"b.stats", $"a.stats").as("stats") ) 的工作方式是首先尝试从coalescediffDf)数据框中获取值。如果该值为null,它将从bdf1)中获取该值。

仅在提供的示例输入数据帧中使用时间过滤器时的结果:

a