如何使用withColumn计算列中的最大值?

时间:2016-11-23 09:00:50

标签: apache-spark dataframe apache-spark-sql aggregate-functions

我正在尝试在Spark 1.6.1 中计算以下DataFrame的最大值:

val df = sc.parallelize(Seq(1,2,3)).toDF("id")

第一种方法是选择最大值,并按预期工作:

df.select(max($"id")).show

第二种方法可能是使用withColumn,如下所示:

df.withColumn("max", max($"id")).show

但遗憾的是它失败并显示以下错误消息:

  

org.apache.spark.sql.AnalysisException:表达式'id'既不是   在集团中出现,也不是集合函数。添加到组   如果您不关心哪个值,请通过或包装在first()(或first_value)中   你得到。;

如何在没有任何withColumnWindow的{​​{1}}函数中计算最大值?如果不可能,我如何使用groupBy

在此特定情况下执行此操作

3 个答案:

答案 0 :(得分:1)

正确的方法是将聚合计算为单独的查询,并与实际结果结合。与窗口函数不同,它在此处的许多答案中都提出了建议,它不需要对单个分区进行随机组合,并且适用于大型数据集。

可以withColumn使用单独的操作来完成此操作:

import org.apache.spark.sql.functions.{lit, max}

df.withColumn("max", lit(df.agg(max($"id")).as[Int].first))

但是使用显式的方法更干净:

import org.apache.spark.sql.functions.broadcast

df.crossJoin(broadcast(df.agg(max($"id") as "max")))

或隐式交叉联接:

spark.conf.set("spark.sql.crossJoin.enabled", true)

df.join(broadcast(df.agg(max($"id") as "max")))

答案 1 :(得分:-1)

functions in Apache Spark

的类别很少
  • 聚合函数,例如max,当我们想要将多行聚合到一个
  • 当我们想要将一列转换为另一列时,无聚合函数abs,isnull
  • 收集功能,例如爆炸,当一行将扩展到多行时。

隐式聚合

当我们想要将更多行聚合为一个时,他们习惯了。

以下代码内部有一个聚合。

df.select(max($"id")).explain

== Physical Plan ==
*HashAggregate(keys=[], functions=[max(id#3)])
+- Exchange SinglePartition
   +- *HashAggregate(keys=[], functions=[partial_max(id#3)])
      +- *Project [value#1 AS id#3]
         +- Scan ExistingRDD[value#1]

我们也可以在select中使用多个聚合函数。

df.select(max($"id"), min($"id")).explain

聚合函数不能直接与非聚合函数混合使用

以下代码将报告错误。

df.select(max($"id"), $"id")

df.withColumn("max", max($"id"))

因为max($"id")的值很少,所以$"id"

over

汇总

在这种情况下,将应用分析函数并显示结果集中的所有行。

我们可以使用

df.select(max($"id").over, $"id").show

df.withColumn("max", max($"id").over).show

答案 2 :(得分:-1)

这是Spark 2.0

使用withColumn和窗口函数,它可以如下:

df.withColumn("max", max('id) over)

请注意空over,假设"空"窗口(相当于over ())。

如果您需要更完整的WindowSpec,则可以执行以下操作(同样,这是2.0):

import org.apache.spark.sql.expressions._
// the trick that has performance cost (!)
val window = Window.orderBy()
df.withColumn("max", max('id) over window).show

请注意,Spark本身报告的代码存在严重的性能问题:

  

WARN WindowExec:没有为Window操作定义分区!将所有数据移动到单个分区,这可能会导致严重的性能下降。