将Dataframe转换为scala Mutable映射不会产生相同数量的记录

时间:2017-10-28 22:08:18

标签: scala dictionary apache-spark dataframe collections

我是Scala / spark的新手。我正在研究Scala / Spark应用程序,它从蜂巢表中选择几列,然后将其转换为Mutable映射,第一列是键,第二列是值。例如:

+--------+--+
| 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

我的想法是将Dataframes转换为collections并进行一些比较。我也从其他表中获取数据,但它们只是单列。我将它们转换为ArrayBuffer[String]没有问题 - 计数匹配。

我不明白我为什么遇到testMap的问题。通常,DF中的计数行和Map的大小应匹配,对吗?

是因为记录太多了吗?如何在DF中将相同数量的记录导入Map

任何帮助将不胜感激。谢谢。

2 个答案:

答案 0 :(得分: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的总数应与原始行数匹配。

答案 1 :(得分:0)

如果您向地图添加具有重复键的条目,则会自动删除重复项。所以你要比较的是:

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