val df = (Seq((1, "a", "10"),(1,"b", "12"),(1,"c", "13"),(2, "a", "14"),
(2,"c", "11"),(1,"b","12" ),(2, "c", "12"),(3,"r", "11")).
toDF("col1", "col2", "col3"))
所以我有一个包含3列的火花数据帧。
我的要求实际上是我需要执行两个级别的groupby,如下所述。
级别1: 如果我在col1上进行groupby并做一个Col3的总和。我将在两列以下。 col1 总和(col3) 我会在这里松开col2。
级别2: 如果我想再次按col1和col2分组并做一个Col3的总和,我将得到3列以下。 col1 2. col2 3. sum(col3)
我的要求实际上是我需要执行两个级别的groupBy并在最后一个数据帧中拥有这两个列(level1的sum(col3),level2的sum(col3))。
我怎么能这样做,任何人都可以解释一下吗?
火花:1.6.2 斯卡拉:2.10答案 0 :(得分:15)
一种选择是分别进行两次求和,然后加入它们:
(df.groupBy("col1", "col2").agg(sum($"col3").as("sum_level2")).
join(df.groupBy("col1").agg(sum($"col3").as("sum_level1")), Seq("col1")).show)
+----+----+----------+----------+
|col1|col2|sum_level2|sum_level1|
+----+----+----------+----------+
| 2| c| 23.0| 37.0|
| 2| a| 14.0| 37.0|
| 1| c| 13.0| 47.0|
| 1| b| 24.0| 47.0|
| 3| r| 11.0| 11.0|
| 1| a| 10.0| 47.0|
+----+----+----------+----------+
另一种选择是使用窗口函数,考虑到level1_sum是由col1
分组的level2_sum的总和:
import org.apache.spark.sql.expressions.Window
val w = Window.partitionBy($"col1")
(df.groupBy("col1", "col2").agg(sum($"col3").as("sum_level2")).
withColumn("sum_level1", sum($"sum_level2").over(w)).show)
+----+----+----------+----------+
|col1|col2|sum_level2|sum_level1|
+----+----+----------+----------+
| 1| c| 13.0| 47.0|
| 1| b| 24.0| 47.0|
| 1| a| 10.0| 47.0|
| 3| r| 11.0| 11.0|
| 2| c| 23.0| 37.0|
| 2| a| 14.0| 37.0|
+----+----+----------+----------+