2017-10-28 78 views
0

我是Scala/spark的新手。我正在研究Scala/Spark應用程序,該應用程序從配置單元表中選擇幾列,然後將其轉換爲可變映射,其中第一列是鍵,第二列是值。例如:將Dataframe轉換爲Scala可變映射不會產生相同數量的記錄

+--------+--+ 
| c1  |c2| 
+--------+--+ 
|Newyork |1 | 
| LA |0 | 
|Chicago |1 | 
+--------+--+ 

將被轉換爲Scala.mutable.Map(Newyork -> 1, LA -> 0, Chicago -> 1)

這裏是我的上述轉換的代碼:

val testDF = hiveContext.sql("select distinct(trim(c1)),trim(c2) from default.table where trim(c1)!=''") 
val testMap = scala.collection.mutable.Map(testDF.map(r => (r(0).toString,r(1).toString)).collectAsMap().toSeq: _*) 

我有與轉換沒有問題。然而,當我打印的行中Dataframe計數和Map的大小,我看到他們不匹配:

println("Map - "+testMap.size+" DataFrame - "+testDF.count) 
//Map - 2359806 DataFrame - 2368295 

我的想法是轉換Dataframescollections並進行一些比較。我也從其他表中獲取數據,但它們只是單列。我沒有問題將它們轉換爲ArrayBuffer[String] - 計數匹配。

我不明白爲什麼我對testMap有問題。通常,DF中的計數行和Map的大小應該匹配,對不對?

是否因爲記錄太多?我如何在DF中獲得與Map相同的記錄數?

任何幫助,將不勝感激。謝謝。

回答

2

我相信計數不匹配是由Map中刪除重複密鑰(即城市名稱)引起的。按照設計,Map通過刪除所有重複項來保留唯一鍵。例如:

val testDF = Seq(
    ("Newyork", 1), 
    ("LA", 0), 
    ("Chicago", 1), 
    ("Newyork", 99) 
).toDF("city", "value") 

val testMap = scala.collection.mutable.Map(
    testDF.rdd.map(r => (r(0).toString, r(1).toString)). 
    collectAsMap().toSeq: _* 
) 
// testMap: scala.collection.mutable.Map[String,String] = 
// Map(Newyork -> 99, LA -> 0, Chicago -> 1) 

您可能想要使用不同的集合類型或在Map鍵中包含標識字段以使其唯一。根據您的數據處理需求,您可以通過groupBy還的數據彙總到一個像地圖非數據幀象下面這樣:

testDF.groupBy("city").agg(count("value").as("valueCount")) 

在這個例子中,總的valueCount應與原來的行數。

+0

謝謝你的答案!我想知道當我使用配置單元的'distinct'功能選擇值時,怎麼會有重複。後來我注意到這些值中有逗號,並使用'regexp_replace'來刪除所有逗號。但我仍然不明白如何能有這麼多重複首先。對此有何想法? – Hemanth

+0

無論您如何對列進行分組,標準SQL都會將「distinct」關鍵字應用於「select」子句中所有列的組合。換句話說,'select distinct(col_a),col_b ...'與'select distinct col_a,col_b ...'沒有區別,因此只保證'col_a + col_b'是唯一的。 –

0

如果您將具有重複鍵的條目添加到地圖中,重複項會自動刪除。所以你應該比較的是:

println("Map - "+testMap.size+" DataFrame - "+testDF.select($"c1").distinct.count) 
相關問題