2017-09-19 81 views
0

我這裏有兩個數據幀: DF1是這裏比較兩個數據幀,僅輸出DIFF列的每列

+----------+------+---------+--------+------+ 
|  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輸出一次只有一列。

問候, 蘇達

+0

它似乎並沒有產生預期的輸出或者 - 如果你有列Y值X在兩個dataframes兩個不同的'OrgId's - 這些將不會出現(因爲'除了'會移除X),但它們出現在不同的OrgId中單曲。 –

+0

@TzachZohar對不起,我編輯了我的問題...我想我必須找出一些其他的方式... – SUDARSHAN

+0

什麼是_schema_的預期結果? DataFrame中的行必須全部具有相同的結構,不能有一列有N列,另一行有N + 1列。你是否還想有與輸入類似的單獨列,在沒有差異的地方使用'null'?或者你想將所有列「合併」到一個數組/地圖列中?請定義所需輸出的EXACT結構。 –

回答

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|!|]| 
// +----------+----------+---------+--------+------------+ 
+0

這是我需要的,但是我們能不能用一些空格替換null? – SUDARSHAN

+0

不是真的 - 因爲一個列必須有一個類型,而這些列的類型是'Array [Int]'或'Array [String]' - 「空格」不是數組。更重要的是 - 你應該確保你知道是否(以及爲什麼)空白區會更好 - 我不明白它是如何可用的。 –