Apache spark 分组和聚合两次
我有一个如下所示的数据帧:Apache spark 分组和聚合两次,apache-spark,pyspark,Apache Spark,Pyspark,我有一个如下所示的数据帧: City State Hour Score Percentage DEN CO 1 0 0 DEN CO 1 0 0 DEN CO 2 2 99 DEN CO 3 0 0 NYC NYC 1 0
City State Hour Score Percentage
DEN CO 1 0 0
DEN CO 1 0 0
DEN CO 2 2 99
DEN CO 3 0 0
NYC NYC 1 0 0
City State total_hours total_scores total_perct. total_volume
DEN CO [1,2,3] [0,2,0] [0,99,0] [2,1,1]
NYC NYC [1] [0] [0] [1]
我希望它看起来像这样:
City State Hour Score Percentage
DEN CO 1 0 0
DEN CO 1 0 0
DEN CO 2 2 99
DEN CO 3 0 0
NYC NYC 1 0 0
City State total_hours total_scores total_perct. total_volume
DEN CO [1,2,3] [0,2,0] [0,99,0] [2,1,1]
NYC NYC [1] [0] [0] [1]
对于total_hours
我只是为City
和State
为total_scores
做了一个收集每个特定小时的集合,然后收集所有小时的所有分数。例:第一小时的分数是2分,0分和0分,我只取其中一分,然后第二小时的分数是1分,所以它变成了[0,2]
。与总销售额相同。
对于总销售额
,我计算每小时的计数,并收集同一城市和州的所有小时的列表
这基本上就是我想要实现的。如果我这样做groupBy
:
df.groupBy("city", "state", "hour")
.agg(collect_set("Hour").alias("total_hours"), collect_set("Score").alias("total_scores"),
collect_set("Percentage").alias("total_perct."), count("hour").alias("total_volume"))
我将获得以下数据帧:
City State total_hours total_scores total_perct. total_volume
DEN CO [1] [0] [0] 2
DEN CO [2] [2] [99] 1
DEN CO [3] [0] [0] 1
NYC NYC [1] [0] [0] 1
我不明白从这里该怎么办。我怎样才能得到我现在所拥有的并取得最终的结果?我正在使用PySpark。Spark<2.4 需要使用
udf
,但在这种情况下速度非常慢:(
Spark 2.4+
好的,这是与收集集
和收集列表
一起使用的
from pyspark.sql.functions import max, count, col, collect_list, flatten
df.groupBy('City', 'State', 'Hour') \
.agg(collect_set(col('Score')).alias('Score'), collect_set(col('Percentage')).alias('Percentage'), count(col('Hour')).alias('total_volume')) \
.orderBy('City', 'State', 'Hour') \
.groupBy('City', 'State') \
.agg(collect_list(col('Hour')).alias('total_hours'), flatten(collect_list(col('Score'))).alias('total_scores'), flatten(collect_list(col('Percentage'))).alias('total_perct.'), collect_list(col('total_volume')).alias('total_volume')) \
.show(10, False)
+----+-----+-----------+------------+------------+------------+
|City|State|total_hours|total_scores|total_perct.|total_volume|
+----+-----+-----------+------------+------------+------------+
|NYC |NYC |[1] |[0] |[0] |[1] |
|DEN |CO |[1, 2, 3] |[0, 2, 0] |[0, 99, 0] |[2, 1, 1] |
+----+-----+-----------+------------+------------+------------+
如果在这一步中没有按排序,则结果列表的顺序将是混合的。另一种方法是使用窗口计算小时的出现次数,然后根据分区筛选1个索引(idx),然后按groupby+collect\u列表
import pyspark.sql.functions as F
from pyspark.sql.window import Window
输出:
+----+-----+----------+-----------+----------------+------------+
|City|State|total_Hour|total_Score|total_Percentage|total_Volume|
+----+-----+----------+-----------+----------------+------------+
| NYC| NYC| [1]| [0]| [0]| [1]|
| DEN| CO| [1, 2, 3]| [0, 2, 0]| [0, 99, 0]| [2, 1, 1]|
+----+-----+----------+-----------+----------------+------------+
为什么你需要按小时分组?哦,我明白了。有点复杂。@Lamanus我这样做只是为了得到那一小时的总音量,我不确定是否有更好的方法来获得每小时的总音量,然后收集所有小时的所有音量如何合并第一行和第二行?我知道你想得到计数,
2
但是分数和百分比呢?我可以简单地添加分数,但是百分比是多少?其中一个…嗯…@Lamanus我不确定这是否回答了你的问题,但是分数和百分比我们每小时都有一个集合,然后返回并收集所有,例如,如果第1小时的分数为0,1,1,1,2,那么该集合将是[0,1,2]如果第2小时的分数为0,0,0,则结果为[0,1,2,0]百分比也是一样。嗯,你是如何得到扁平化的?在pyspark.sql.functions库中,它说没有名为flatten的函数。我错过了包导入行并添加了。是的,它给了我一个错误,说没有名为flatte的函数:`ImportError:cannot import name'flatte'