spark业务开发-聚合(agg)

spark业务开发-聚合(agg)

输入数据
name,profession,enroll,score
曾凰妹,金融学,北京电子科技学院,637
谢德炜,金融学,北京电子科技学院,542
林逸翔,金融学,北京电子科技学院,543
王丽云,金融学,北京电子科技学院,626
吴鸿毅,金融学,北京电子科技学院,591
施珊珊,经济学类,北京理工大学,581
柯祥坤,经济学类,北京理工大学,650
庄劲聪,经济学类,北京理工大学,551
吴雅思,经济学类,北京理工大学,529
周育传,经济学类,北京理工大学,682
丁俊伟,通信工程,北京电子科技学院,708
庄逸琳,通信工程,北京电子科技学院,708
吴志发,通信工程,北京电子科技学院,578
肖妮娜,通信工程,北京电子科技学院,557
蔡建明,通信工程,北京电子科技学院,583
林逸翔,通信工程,北京电子科技学院,543

数据随便构造的,无任何现实意义

输出数据
+----------------+----------+----+--------+------+------+-----------------+----+-----------------+
|          enroll|profession|总数|去重总数|最小值|最大值|           平均值|总和|         标准方差|
+----------------+----------+----+--------+------+------+-----------------+----+-----------------+
|北京电子科技学院|  通信工程|   6|       6|   543|   708|612.8333333333334|3677| 75.1143572605575|
|北京电子科技学院|    金融学|   5|       5|   542|   637|            587.8|2939|44.70682274552733|
|    北京理工大学|  经济学类|   5|       5|   529|   682|            598.6|2993|65.22499520889212|
+----------------+----------+----+--------+------+------+-----------------+----+-----------------+
程序代码
package com.cch.bigdata.spark.process.agg

import com.cch.bigdata.spark.process.AbstractTransform
import org.apache.spark.sql.functions._
import org.apache.spark.sql.{Column, DataFrame, functions}

import scala.collection.mutable.ListBuffer

//聚合操作
class Aggregater extends AbstractTransform {

  //需要分组的列数组
  private val group_columns = Array("enroll","profession")

  //聚合操作的字段
  private val agg_columns = Array("name","name","score","score","score","score","score")

  //聚合模式
  //Count:数量
  //DistinctCount:去重数量
  //min:最小值
  //max:最大值
  //avg:平均值
  //sum:求和
  //Stddev:标准方差
  private val agg_mode = Array("Count","DistinctCount","min","max","avg","sum","Stddev")

  //列对应的中文名称
  private val new_column_cnames = Array("总数","去重总数","最小值","最大值","平均值","总和","标准方差")


  override def process(): Unit = {
    if (agg_columns.isEmpty) {
      throw new RuntimeException("聚合列不能为空")
    }

    if (agg_mode.isEmpty) {
      throw new RuntimeException("聚合模式不能为空")
    }

    if (agg_columns.length != agg_mode.length) {
      throw new RuntimeException("聚合列和聚合模式不匹配")
    }


    //获取输入流
    val df: DataFrame = loadCsv("src/main/resources/csv/admission.csv",spark)

    //构造结果列list,用来存储最后需要聚合的列
    val columnList: ListBuffer[Column] = new ListBuffer()


    var index = 0;
    agg_columns.foreach(c => {
      //聚合模式
      val aggMode: String = agg_mode(index)
      if (aggMode.isEmpty) {
        throw new RuntimeException("聚合模式为空,无法为字段" + c + "做聚合操作")
      }

      var columnNewName: String = new_column_cnames(index)
      if (columnNewName.isEmpty) {
        columnNewName = c
      }

      aggMode match {
        case "Count" => {
          columnList.append(count(c).as(columnNewName))
        }

        case "DistinctCount" => {
          columnList.append(countDistinct(c).as(columnNewName))
        }

        case "min" => {
          columnList.append(min(c).as(columnNewName))
        }

        case "max" => {
          columnList.append(functions.max(c).as(columnNewName))
        }

        case "sum" =>{
          columnList.append(functions.sum(c).as(columnNewName))
        }

        case "avg" => {
          columnList.append(avg(c).as(columnNewName))
        }

        case "Stddev" => {
          columnList.append(stddev(c).as(columnNewName))
        }

        case _ => {
          throw new RuntimeException("聚合策略不正确,仅支持[Count/DistinctCount/min/max/avg/Stddev]")
        }
      }
      index += 1
    })

    //方法1:提起第一个字段,用于后面的agg参数
    //使用这种方式多了一个处理第一个参数的步骤
    //但是可以处理字段别名的问题
    val firstColumn: Column = columnList(0)
    //删除第一个字段
    columnList.remove(0)


    //方法2:构造map数据结构
    // 使用方式简单,但是无法使用as别名
    //    df.groupBy("department").agg(Map(
    //      "age" -> "max",
    //      "expense" -> "sum"
    //    ))


    //如果分组列不为空,先进行分组
    if (!group_columns.isEmpty) {
      //分组聚合
      df.groupBy(group_columns.map(c => {
        col(c)
      }): _*).agg(firstColumn, columnList.map(c => {
        c
      }): _*).show()
    }else{
      //不分组聚合
      df.agg(firstColumn, columnList.map(c => {
        c
      }): _*).show()
    }
  }

  override def getAppName(): String = "聚合操作"
}

package com.cch.bigdata.spark.process

import com.cch.bigdata.spark.process.agg.Aggregater

object AggTest {

  def main(args: Array[String]): Unit = {
    new Aggregater().process()
  }
}

参数解释
  • group_columns:需要进行分组聚合时的列名

  • agg_columns:需要聚合的字段数组

  • agg_mode:聚合方式

  • new_column_cnames:聚合后新列名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值