[英]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中,我將無法找到並刪除countB中的所有密鑰
我已經嘗試過類似的東西:
countsB.keys.foreach(b => {
if(countsB.collect().exists(_ == b)){
countsB.collect().drop(countsB.collect().indexOf(b))
}
})
但似乎並不能通過鍵將其刪除。
建議的代碼存在3個問題:
您正在collect
RDD,這意味着它們不再是RDD,它們將以純Scala集合的形式復制到驅動程序應用程序的內存中,因此,如果數據集很大,則會丟失Spark的並行性並冒出內存不足錯誤的風險
當在不可變的Scala集合(或RDD
)上調用drop
時,您不會更改原始集合,而是會刪除掉這些記錄,從而得到一個新集合,因此您不能指望原始集合會發生變化
您不能在傳遞給任何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
作為參數,並表現等的組合map
和filter
,以及最重要的是:它不會將所有的數據復制到驅動器記憶。
編輯 :正如原型保羅所評論的那樣-您有一個更短,更好的選項- subtractByKey
:
countsB.subtractByKey(countsA)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.