Spark数据帧聚合scala

Posted

技术标签:

【中文标题】Spark数据帧聚合scala【英文标题】:Spark dataframe aggregation scala 【发布时间】:2017-03-09 21:42:47 【问题描述】:
val df = sc.parallelize(Seq((a, 1), (a, null), (b, null)(b, 2),(b, 3),(c, 2),(c, 4),(c, 3))).toDF("col1","col2")

输出应该如下所示。

col1 col2
a    null
b    null
c    4

我知道 col1 上的 groupBy 并获得 col2 的最大值。我可以使用df.groupBy("col1").agg("col2"->"max")

但我的要求是如果有 null 我想选择该记录,但如果没有 null 我想选择 col2 的最大值。

我该怎么做,请帮助我。

【问题讨论】:

尝试使用这个 import org.apache.spark.sql.functions._ df.groupBy("col1").agg(collect_as_list("col2")) 现在你在 col2 上有列表试试你的逻辑,比如 if list.contains(null) return null else max from list 你真的应该重新考虑问题的前提。没有必要在你的 RDD 中有一堆null 大家好,感谢您的回复。我已经通过以下方式做到了这一点。我首先通过将空值更新为该列的字符串“99-99-9999”来修改数据框。然后我按其他列和 agg -->max 对我更新的列进行了分组。这样我的要求就满足了。非常感谢所有回复的人。 @Ramesh :如果您发布答案并接受它会很好。因此,如果其他人正在寻找类似的答案,这将是有帮助的。 【参考方案1】:

正如我所评论的,您对null 的使用会使事情产生不必要的问题,所以如果一开始就没有null 就无法工作,我认为将它变成更有用的东西是最有意义的:

val df = sparkContext.parallelize(Seq((a, 1), (a, null), (b, null), (b, 2),(b, 3),(c, 2),(c, 4),(c, 3)))
        .mapValues  v => Option(v) match 
            case Some(i: Int) => i
            case _ => Int.MaxValue
          
        .groupBy(_._1).map 
            case (k, v) => k -> v.map(_._2).max
        

首先,我使用Option 摆脱null 并将事情从Any 移到Int,这样我就可以享受更多的类型安全。我将 null 替换为 MaxValue,原因我稍后会解释。

然后我 groupBy 像你一样,然后我 map 在组上将键与值的最大值配对,这将是你的原始数据项之一或 MaxValue 其中@987654333 @s 曾经是。如果必须,您可以将它们转回null,但我不会。

可能有一种更简单的方法来完成这一切,但我喜欢将null 替换为MaxValue,这种模式匹配可以帮助我缩小类型范围,而且之后我可以将所有内容都视为相同。

【讨论】:

以上是关于Spark数据帧聚合scala的主要内容,如果未能解决你的问题,请参考以下文章

Spark多个动态聚合函数,countDistinct不起作用

Scala中的Spark分组映射UDF

如何使用 spark-scala 在 spark 数据帧上执行枢轴?

Spark 中的数据框比较:Scala

在 Apache Spark (Scala) 上获取两个数据帧的差异

通过读取具有不同数据类型的 Scala 序列来创建 Spark 数据帧