我正在尝试在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)中 你得到。;
如何在没有任何withColumn
或Window
的{{1}}函数中计算最大值?如果不可能,我如何使用groupBy
?
答案 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)
当我们想要将更多行聚合为一个时,他们习惯了。
以下代码内部有一个聚合。
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操作定义分区!将所有数据移动到单个分区,这可能会导致严重的性能下降。