对spark数据帧的同一列进行多次聚合操作

时间:2016-01-22 19:49:52

标签: apache-spark dataframe apache-spark-sql

我有三个包含以下信息的字符串类型数组:

  • groupBy array:包含我想按照数组对数据进行分组的列的名称。
  • 聚合数组:包含我想要聚合的列的名称。
  • operations array:包含我想要执行的聚合操作

我正在尝试使用spark数据帧来实现这一目标。 Spark数据框提供了agg(),您可以在其中传递Map [String,String](列名和相应的聚合操作)作为输入,但是我想对数据的同一列执行不同的聚合操作。有关如何实现这一目标的任何建议吗?

5 个答案:

答案 0 :(得分:50)

<强> Scala的

例如,您可以将名称为mapping的函数列表映射到函数:

import org.apache.spark.sql.functions.{col, min, max, mean}
import org.apache.spark.sql.Column

val df = Seq((1L, 3.0), (1L, 3.0), (2L, -5.0)).toDF("k", "v")
val mapping: Map[String, Column => Column] = Map(
  "min" -> min, "max" -> max, "mean" -> avg)

val groupBy = Seq("k")
val aggregate = Seq("v")
val operations = Seq("min", "max", "mean")
val exprs = aggregate.flatMap(c => operations .map(f => mapping(f)(col(c))))

df.groupBy(groupBy.map(col): _*).agg(exprs.head, exprs.tail: _*).show
// +---+------+------+------+
// |  k|min(v)|max(v)|avg(v)|
// +---+------+------+------+
// |  1|   3.0|   3.0|   3.0|
// |  2|  -5.0|  -5.0|  -5.0|
// +---+------+------+------+

df.groupBy(groupBy.head, groupBy.tail: _*).agg(exprs.head, exprs.tail: _*).show

不幸的是,内部使用的SQLContext解析器未公开公开,但您始终可以尝试构建纯SQL查询:

df.registerTempTable("df")
val groupExprs = groupBy.mkString(",")
val aggExprs = aggregate.flatMap(c => operations.map(
  f => s"$f($c) AS ${c}_${f}")
).mkString(",")

sqlContext.sql(s"SELECT $groupExprs, $aggExprs FROM df GROUP BY $groupExprs")

<强>的Python

from pyspark.sql.functions import mean, sum, max, col

df = sc.parallelize([(1, 3.0), (1, 3.0), (2, -5.0)]).toDF(["k", "v"])
groupBy = ["k"]
aggregate = ["v"] 
funs = [mean, sum, max]

exprs = [f(col(c)) for f in funs for c in aggregate]

# or equivalent df.groupby(groupBy).agg(*exprs)
df.groupby(*groupBy).agg(*exprs)

另见:

答案 1 :(得分:1)

对于那些想知道如何在python中没有列表解析的情况下如何编写@ zero323答案:

@Input() title: any;
  @Output() pushTitle = new EventEmitter();

  constructor() { }

  ngOnInit() {
    this.title = 'new title';
    this.pushTitle.emit(this.title);
  }

答案 2 :(得分:0)

这是使用Scala时在同一列上应用不同聚合函数的另一种直接方法(这已在Azure Databricks中进行了测试)。

const button = document.querySelector('btn');
button.onclick = changeColor;

答案 3 :(得分:0)

例如,如果您要计算pyspark数据框中每一列的零百分比,我们可以使用表达式在数据框的每一列上执行

from pyspark.sql.functions import count,col

    def count_zero_percentage(c):
        
        pred = col(c)==0
        return sum(pred.cast("integer")).alias(c)
    
    df.agg(*[count_zero_percentage(c)/count('*').alias(c) for c in df.columns]).show()

答案 4 :(得分:-1)

case class soExample(firstName: String, lastName: String, Amount: Int)
val df =  Seq(soExample("me", "zack", 100)).toDF

import org.apache.spark.sql.functions._

val groupped = df.groupBy("firstName", "lastName").agg(
     sum("Amount"),
     mean("Amount"), 
     stddev("Amount"),
     count(lit(1)).alias("numOfRecords")
   ).toDF()

display(groupped)
  

//感谢Zach ..

Zach简化了标记为重复的帖子的答案 schema_of_json()