簡體   English   中英

RDD通過鍵刪除元素

[英]RDD Remove elements by key

我有2個RDD,其中包含以下代碼:

val fileA = sc.textFile("fileA.txt")
val fileB = sc.textFile("fileB.txt")

然后,我通過按鍵映射並縮小它:

val countsB = fileB.flatMap(line => line.split("\n"))
  .map(word => (word, 1))
  .reduceByKey(_+_)

val countsA = fileA.flatMap(line => line.split("\n"))
  .map(word => (word, 1))
  .reduceByKey(_+_)

現在,如果密鑰存在於countA中,我將無法找到並刪除co​​untB中的所有密鑰

我已經嘗試過類似的東西:

countsB.keys.foreach(b => {
  if(countsB.collect().exists(_ == b)){
    countsB.collect().drop(countsB.collect().indexOf(b))
  }
})

但似乎並不能通過鍵將其刪除。

建議的代碼存在3個問題:

  1. 您正在collect RDD,這意味着它們不再是RDD,它們將以純Scala集合的形式復制到驅動程序應用程序的內存中,因此,如果數據集很大,則會丟失Spark的並行性並冒出內存不足錯誤的風險

  2. 當在不可變的Scala集合(或RDD )上調用drop時,您不會更改原始集合,而是會刪除掉這些記錄,從而得到一個集合,因此您不能指望原始集合會發生變化

  3. 您不能在傳遞給任何RDD高階方法的函數中訪問RDD (例如,在這種情況下為foreach )-傳遞給這些方法的任何函數都被序列化並發送給worker,並且RDD (有意地)不可序列化-它將它們提取到驅動程序內存中,對其進行序列化並發送回工作程序沒有任何意義-數據已經在工作程序中分發了!

為了解決所有這些問題-當您要使用一個RDD的數據來轉換/過濾另一個數據時,通常需要使用某種類型的join 在這種情況下,您可以執行以下操作:

// left join, and keep only records for which there was NO match in countsA:
countsB.leftOuterJoin(countsA).collect { case (key, (valueB, None)) => (key, valueB) }

請注意,這個collect ,我使用這里是不collect你用-這其中需要PartialFunction作為參數,並表現等的組合mapfilter ,以及最重要的是:它不會將所有的數據復制到驅動器記憶。

編輯 :正如原型保羅所評論的那樣-您有一個更短,更好的選項- subtractByKey

countsB.subtractByKey(countsA)

暫無
暫無

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

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