加入两个数据帧并用另一个更新一个数据帧记录

时间:2017-09-30 08:28:30

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

所以我有两个数据框。 数据框1如下:

+----------+------+---------+--------+------+
|     OrgId|ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|   136|        4|       1|  I|!||
|4295877346|   136|        4|       1|  I|!||
|4295877341|   138|        2|       1|  I|!||
|4295877341|   141|        4|       1|  I|!||
|4295877341|   143|        2|       1|  I|!||
|4295877341|   145|       14|       1|  I|!||
| 123456789|   145|       14|       1|  I|!||
| 809580109|   145|       9|        9|  I|!||
+----------+------+---------+--------+------+

DataFrame2如下所示

+----------+------+-----------+----------+--------+
|     OrgId|ItemId|segmentId_1|Sequence_1|Action_1|
+----------+------+-----------+----------+--------+
|4295877343|   149|         15|         2|    I|!||
|4295877341|   136|       null|      null|    I|!||
| 123456789|   145|         14|         1|    D|!||
|4295877341|   138|         11|        22|    I|!||
|4295877341|   141|         10|         1|    I|!||
|4295877341|   143|          1|         1|    I|!||
| 809580109|   145|       NULL|      NULL|    I|!||
+----------+------+-----------+----------+--------+

现在我必须将数据帧更新数据第1列与数据帧2的匹配记录连接起来。

现在,两个数据框中的键都是OrgId和ItemId。

所以预期的输出应该是。

+----------+------+---------+--------+------+
|     OrgId|ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877346|   136|        4|       1|  I|!||
|4295877341|   145|       14|       1|  I|!||
|4295877343|   149|       15|       2|  I|!||
|4295877341|   136|     null|    null|  I|!||
|4295877341|   138|       11|      22|  I|!||
|4295877341|   141|       10|       1|  I|!||
|4295877341|   143|        1|       1|  I|!||
| 809580109|   145|       9|        9|  I|!||
+----------+------+---------+--------+------+

所以我需要用数据帧2记录更新数据帧1。 如果在2中没有找到数据框1中的记录,那么我们也需要保留这些记录。 如果在数据帧2中找到任何新记录,则需要在输出中添加该记录

这就是我在做什么..

val df3 = df1.join(df2, Seq("OrgId", "ItemId"), "outer")
  .select($"OrgId", $"ItemId",$"segmentId_1",$"Sequence_1",$"Action_1")
  .filter(!$"Action_1".contains("D"))
    df3.show()

但我的产量低于产量。

+----------+------+-----------+----------+--------+
|     OrgId|ItemId|segmentId_1|Sequence_1|Action_1|
+----------+------+-----------+----------+--------+
|4295877343|   149|         15|         2|    I|!||
|4295877341|   136|       null|      null|    I|!||
|4295877341|   138|         11|        22|    I|!||
|4295877341|   141|         10|         1|    I|!||
|4295877341|   143|          1|         1|    I|!||
+----------+------+-----------+----------+--------+

我没有从数据框1获得4295877346| 136| 4| 1| I|!|记录...

left_outer给出了我的输出

+----------+------+-----------+----------+--------+
|     OrgId|ItemId|segmentId_1|Sequence_1|Action_1|
+----------+------+-----------+----------+--------+
|4295877341|   136|       null|      null|    I|!||
|4295877341|   138|         11|        22|    I|!||
|4295877341|   141|         10|         1|    I|!||
|4295877341|   143|          1|         1|    I|!||
+----------+------+-----------+----------+--------+

2 个答案:

答案 0 :(得分:1)

让我先解释一下你的错误。

如果你只加入如下

val df3 = df1.join(df2, Seq("OrgId", "ItemId"), "outer")
df3.show()

你会得到

+----------+------+---------+--------+------+-----------+----------+--------+
|     OrgId|ItemId|segmentId|Sequence|Action|segmentId_1|Sequence_1|Action_1|
+----------+------+---------+--------+------+-----------+----------+--------+
|4295877346|   136|        4|       1|  I|!||       null|      null|    null|
|4295877341|   145|       14|       1|  I|!||       null|      null|    null|
|4295877343|   149|     null|    null|  null|         15|         2|    I|!||
|4295877341|   136|        4|       1|  I|!||       null|      null|    I|!||
| 123456789|   145|       14|       1|  I|!||         14|         1|    D|!||
|4295877341|   138|        2|       1|  I|!||         11|        22|    I|!||
|4295877341|   141|        4|       1|  I|!||         10|         1|    I|!||
|4295877341|   143|        2|       1|  I|!||          1|         1|    I|!||
+----------+------+---------+--------+------+-----------+----------+--------+

很明显,代码中的filter正在过滤null以及Action_1

因此,您的工作代码是将null之后的join值更改为来自存在数据的其他表的有效数据。

val df3 = df1.join(df2, Seq("OrgId", "ItemId"), "outer")
  .withColumn("segmentId_1", when($"segmentId_1".isNotNull, $"segmentId_1").otherwise($"segmentId"))
  .withColumn("Sequence_1", when($"Sequence_1".isNotNull, $"Sequence_1").otherwise($"Sequence"))
  .withColumn("Action_1", when($"Action_1".isNotNull, $"Action_1").otherwise($"Action"))
  .select($"OrgId", $"ItemId",$"segmentId_1",$"Sequence_1",$"Action_1")
  .filter(!$"Action_1".contains("D") )
df3.show()

你应该得到所需的输出

+----------+------+-----------+----------+--------+
|     OrgId|ItemId|segmentId_1|Sequence_1|Action_1|
+----------+------+-----------+----------+--------+
|4295877346|   136|          4|         1|    I|!||
|4295877341|   145|         14|         1|    I|!||
|4295877343|   149|         15|         2|    I|!||
|4295877341|   136|       null|      null|    I|!||
|4295877341|   138|         11|        22|    I|!||
|4295877341|   141|         10|         1|    I|!||
|4295877341|   143|          1|         1|    I|!||
+----------+------+-----------+----------+--------+

答案 1 :(得分:0)

尝试left-outer而不是outer:

val df3 = df1.join(df2, Seq("OrgId", "ItemId"), "left_outer")
  .select($"OrgId", $"ItemId",$"segmentId_1",$"Sequence_1",$"Action_1")
  .filter(!$"Action_1".contains("D"))
    df3.show()

左外侧应保留左侧的所有非匹配。

一个很好的教程here