假设我有一张表:
id,date,value
1,2017-02-12,3
2,2017-03-18,2
1,2017-03-20,5
1,2017-04-01,1
3,2017-04-01,3
2,2017-04-10,2
我已将此作为数据框(它来自Hive表)
现在,我想要一个看起来像(逻辑上)的输出:
id, count($"date">"2017-03"), sum($"value" where $"date">"2017-03"), count($"date">"2017-02"), sum($"value" where $"date">"2017-02")
我试图在单个agg()中表达这个,但我无法弄清楚如何做内部条件。我知道如何在聚合之前进行过滤,但这并不是我需要的两个不同的子范围。
// doesn't do the right thing
myDF.where($"date">"2017-03")
.groupBy("id")
.agg(sum("value") as "value_03", count("value") as "count_03")
.where($"date">"2017-04")
.agg(sum("value") as "value_04", count("value") as "value_04")
在SQL中,我会把所有聚合放在一个SELECT语句中,条件在count
/ sum
子句中。如何在Spark with Scala中使用DataFrames
做类似的事情?
我能想到的最接近的是计算groupBy(
之前每个窗口中每个元组的成员资格,并对该成员资格时间值(和计数的直接总和)进行求和。似乎应该有<{1}}中有条件的表达方式更好的方法,但我找不到它。
答案 0 :(得分:3)
在SQL中,我会把所有聚合放在一个SELECT语句中,条件在count / sum子句中。
你可以在这里完成同样的事情:
import org.apache.spark.sql.functions.{sum, when}
myDF
.groupBy($"id")
.agg(
sum(when($"date" > "2017-03", $"value")).alias("value3"),
sum(when($"date" > "2017-04", $"value")).alias("value4")
)
+---+------+------+
| id|value3|value4|
+---+------+------+
| 1| 6| 1|
| 3| 3| 3|
| 2| 4| 2|
+---+------+------+