Spark分组和自定义聚合

时间:2015-08-04 18:59:51

标签: apache-spark apache-spark-sql apache-spark-1.4

我的数据如下,

n1  d1  un1 mt1 1
n1  d1  un1 mt2 2
n1  d1  un1 mt3 3
n1  d1  un1 mt4 4
n1  d2  un1 mt1 3
n1  d2  un1 mt3 3
n1  d2  un1 mt4 4
n1  d2  un1 mt5 6
n1  d2  un1 mt2 3

我希望得到如下输出

n1 d1 un1 0.75
n1 d2 un1 1.5

i,在第1列,第2列和第3列进行分组,第4列按照以下公式进行, 第4列=组内,(mt1 + mt2)/ mt4

我正在尝试使用Spark DF 假设数据在数据帧a中,列名为n,d,un,mt,r 我正在尝试这个。

sqlContext.udf.register("aggUDF",(v:List(mt,r))=> ?)
val b = a.groupBy("n","d","un").agg(callUdf("aggUDF",List((mt,r)) should go here))

1 个答案:

答案 0 :(得分:4)

如果我理解正确,你首先要计算mt1和mt2的行总和,然后除以mt4中每个不同的n1,d1,un1的总和。

虽然可以像上面的回答一样使用自定义聚合功能,但你也可以使用一点暴力(我将在pyspark中显示它,但你应该能够轻松地转换为scala)。

假设您的原始数据框名为df且列按顺序排列:n,d,un,mt,r

首先为mt1,mt2和mt4中的每一个创建一个新列,如下所示:

from pyspark.sql import functions as F
newdf = df.withColumn("mt1", when(df.mt == "mt1", df.r).otherwise(0).alias("mt1"))
newdf = newdf .withColumn("mt2", when(newdf.mt == "mt2", newdf .r).otherwise(0).alias("mt2"))
newdf = newdf .withColumn("mt4", when(newdf.mt == "mt4", newdf .r).otherwise(0).alias("mt4"))

现在按前三个值进行分组,并将聚合作为新3个值的总和。

aggregated = newdf.groupBy(["n","d","n"]).agg(F.sum(newdf.mt1).alias("sum_mt1"),F.sum(newdf.mt2).alias("sum_mt2"), F.sum(newdf.mt4).alias("sum_mt4"))

现在只需进行计算:

final = aggregated.withColumn("res", (aggregated.sum_mt1 +  aggregated.sum_mt2) / aggregated.sum_mt4)    

不是最优雅的解决方案,但它可能适合您...