簡體   English   中英

合並兩個RDD Spark Spark Scala,保持右側

[英]union two RDDs Spark scala, keeping the right side

我有兩個Spark數據框,結構如下。 如使用sqlContext之前閱讀的。

 itens.columns (scala command) 
 Array[String] = Array(id_location,id_item, name, price)

 rdd1 
 [1,1,item A,10]
 [1,2,item b,12]
 [1,3,item c,12]

 rdd2
 [1,2,item b,50]
 [1,4,item c,12]
 [1,5,item c,12]

我想要基於組合鍵(id_location,id_item)的以下結果

 [1,1,item A,10]
 [1,2,item b,50]
 [1,3,item c,12]
 [1,4,item c,12]
 [1,5,item c,12]

因此,我想要一個具有不同iten的結果(關於組合鍵),但是當我在兩個rdds中找到具有相同鍵的記錄時,我只想保留rdd2中的記錄。

有人有這種要求嗎?

我正在使用Spark和Scala。

最好的問候拉斐爾。

我是Spark的新手,所以可能有更好的方法,但是您是否可以映射到一對RDD(基於您的復合鍵),然后執行fullOuterJoin,僅使用結果數據中“左”邊和“右”邊都有數據嗎?

粗糙的偽代碼:

val pairRdd1 = rdd1 map {
  line => 
    (line(0)+line(1), line)
}

val pairRdd2 = rdd2 map {
  line => 
    (line(0)+line(1), line)
}

val joined = pairRdd1.fullOuterJoin(pairRdd2)

joined map {
  (id, left, right) =>
    right.getOrElse(left.get)
}

如果我早上有時間,我將嘗試結合一個可行的例子。 希望有幫助!

@Steven有正確的想法。 您需要將數據集映射到鍵值對,然后執行外部outerjoin

val rdd1 = sc.parallelize(List((1,1,"item A",10),(1,2,"item b",12),(1,3,"item c",12)))
val rdd2 = sc.parallelize(List((1,2,"item b",50),(1,4,"item c",12),(1,5,"item c",12)))

val rdd1KV = rdd1.map{case(id_location,id_item, name, price) => ((id_location, id_item), (name, price))}
val rdd2KV = rdd2.map{case(id_location,id_item, name, price) => ((id_location, id_item), (name, price))}

val joined = rdd1KV.fullOuterJoin(rdd2KV)

val res = joined.map{case((id_location, id_item),(leftOption, rightOption)) =>
    val values = rightOption.getOrElse(leftOption.get)
    (id_location, id_item, values._1, values._2)
}

這將為您提供所需的結果。

看起來@Steven的回答在邏輯上是不錯的,但是如果您的數據沒有很多相交的元素(即完整的外部聯接將產生巨大的數據集),則可能會遇到問題。 您還使用了DataFrames,因此對於可以通過DataFrames API完成的任務而言,轉換為RDD然后再轉換為DataFrames似乎過多。 我將在下面介紹如何執行此操作。

讓我們從一些示例數據開始(從您的示例中獲取):

val rdd1 = sc.parallelize(Array((1,1,"item A",10), (1,2,"item b",12), (1,3,"item c",12)))
val rdd2 = sc.parallelize(Array((1,2,"item b",50), (1,4,"item c",12), (1,5,"item c",12)))

接下來,我們可以在單獨的列別名下將它們轉換為DataFrames。 在這里,我們在df1df2使用了不同的別名,因為當我們最終連接這兩個DataFrame時,可以更容易地編寫后續的select(如果有一種方法可以在連接后標識列的來源,則沒有必要)。 請注意,兩個DataFrame的並集都包含要過濾的行。

val df1 = rdd1.toDF("id_location", "id_item", "name", "price")
val df2 = rdd2.toDF("id_location_2", "id_item_2", "name_2", "price_2")

// df1.unionAll(df2).show()
// +-----------+-------+------+-----+
// |id_location|id_item|  name|price|
// +-----------+-------+------+-----+
// |          1|      1|item A|   10|
// |          1|      2|item b|   12|
// |          1|      3|item c|   12|
// |          1|      2|item b|   50|
// |          1|      4|item c|   12|
// |          1|      5|item c|   12|
// +-----------+-------+------+-----+

在這里,我們首先將鍵上的兩個DataFrames連接在一起,它們是df1df2的前兩個元素。 然后,我們通過選擇行(基本上來自df1 )來創建另一個DataFrame,其中存在來自df2具有相同聯接鍵的行。 之后,我們在df1上運行except,以從先前創建的DataFrame中刪除所有行。 這可以看作是一個補充,因為我們基本上要做的是從df1中刪除所有行,而df2存在相同的行("id_location", "id_item") 最后,我們將補碼與df2結合在一起以生成輸出DataFrame。

val df_joined = df1.join(df2, (df1("id_location") === df2("id_location_2")) && (df1("id_item") === df2("id_item_2")))
val df1_common_keyed = df_joined.select($"id_location", $"id_item", $"name", $"price")
val df1_complement = df1.except(df1_common_keyed)
val df_union = df1_complement.unionAll(df2)

// df_union.show()
// +-----------+-------+------+-----+
// |id_location|id_item|  name|price|
// +-----------+-------+------+-----+
// |          1|      3|item c|   12|
// |          1|      1|item A|   10|
// |          1|      2|item b|   50|
// |          1|      4|item c|   12|
// |          1|      5|item c|   12|
// +-----------+-------+------+-----+

同樣,就像@Steven所建議的那樣,您可以通過將DataFrames轉換為RDD並與其一起運行來使用RDD API。 如果這是您要執行的操作,則以下是使用上面的subtractByKey()和輸入RDD來完成所需操作的另一種方法:

val keyed1 = rdd1.keyBy { case (id_location, id_item, _, _) => (id_location, id_item) }
val keyed2 = rdd2.keyBy { case (id_location, id_item, _, _) => (id_location, id_item) }
val unionRDD = keyed1.subtractByKey(keyed2).values.union(rdd2)

// unionRDD.collect().foreach(println)
// (1,1,item A,10)
// (1,3,item c,12)
// (1,2,item b,50)
// (1,4,item c,12)
// (1,5,item c,12)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM