比较两个数据帧的每列,并仅输出差异列

时间:2017-09-19 13:42:30

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

我这里有两个数据框: df1在这里

+----------+------+---------+--------+------+
|     OrgId|ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|   136|        9|       1|  I|!||
|4295877342|   111|        4|       2|  I|!||
|4295877343|   138|        2|       1|  I|!||
|4295877344|   141|        4|       1|  I|!||
|4295877345|   143|        2|       1|  I|!||
|4295877346|   145|       14|       1|  d|!||
+----------+------+---------+--------+------+

df2在这里:

+----------+------+---------+--------+------+
|     OrgId|ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|   136|        4|       1|  I|!||
|4295877342|   136|        4|       1|  I|!||
|4295877343|   900|        2|       1|  K|!||
|4295877344|   141|        4|       1|  D|!||
|4295877345|   111|        2|       1|  I|!||
|4295877346|   145|       14|       1|  I|!||
|4295877347|   145|       14|       1|  I|!||
+----------+------+---------+--------+------+

如果df1不在df2中,我需要的只是所有列值。 如下......

4295877341|^|segmentId=9,segmentId=4|^|1|^|I|!|
4295877342|^|ItemId=111,ItemId=136|^|Sequence=2,Sequence=1|^|I|!|

等等每一行......

这里OrgId是我的两个数据帧的主键。

所以基本上对于每个OrgId我需要收集两个版本,只是列改变了值。

这是我到目前为止所尝试过的。

val columns = df1.schema.fields.map(_.name)
val selectiveDifferences = columns.map(col => 
df1.select(col).except(df2.select(col)))
selectiveDifferences.map(diff => {if(diff.count > 0) diff.show})

但它只给我一个列的Except输出。

此致 苏达

1 个答案:

答案 0 :(得分:1)

您没有为输出定义所需的结构,因此我假设将列保持分离,每列包含不同值的数组null如果他们匹配就足够了:

// list of columns to compare
val cols = df1.columns.filter(_ != "OrgId").toList

// function to create an expression that results in null for similar values,
// and with a two-item array with the differing values otherwise
def mapDiffs(name: String) = when($"l.$name" === $"r.$name", null)
  .otherwise(array($"l.$name", $"r.$name"))
  .as(name)

// joining the two DFs on OrgId
val result = df1.as("l")
  .join(df2.as("r"), "OrgId")
  .select($"OrgId" :: cols.map(mapDiffs): _*)

result.show()
// +----------+----------+---------+--------+------------+
// |     OrgId|    ItemId|segmentId|Sequence|      Action|
// +----------+----------+---------+--------+------------+
// |4295877341|      null|   [9, 4]|    null|        null|
// |4295877342|[111, 136]|     null|  [2, 1]|        null|
// |4295877343|[138, 900]|     null|    null|[I|!|, K|!|]|
// |4295877344|      null|     null|    null|[I|!|, D|!|]|
// |4295877345|[143, 111]|     null|    null|        null|
// |4295877346|      null|     null|    null|[d|!|, I|!|]|
// +----------+----------+---------+--------+------------+