一.概述

  在许多数据中,都存在类别的数据,在一些功能中需要根据类别分别获取前几或后几的数据,用于数据可视化或异常数据预警。在这种情况下,实现分组TopN就显得非常重要了,因此,使用了Spark聚合函数和排序算法实现了分布式TopN计算功能。

  

二.代码实现

 package scala

 import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession} /**
* 计算分组topN
* Created by Administrator on 2019/11/20.
*/
object GroupTopN {
Logger.getLogger("org").setLevel(Level.WARN) // 设置日志级别
def main(args: Array[String]) {
//创建测试数据
val test_data = Array("CJ20191120,201911", "CJ20191120,201910", "CJ20191105,201910", "CJ20191105,201909", "CJ20191111,201910")
val spark = SparkSession.builder().appName("GroupTopN").master("local[2]").getOrCreate()
val sc = spark.sparkContext
val test_data_rdd = sc.parallelize(test_data).map(row => {
val Array(scene, cycle) = row.split(",")
Row(scene, cycle)
})
// 设置数据模式
val structType = StructType(Array(
StructField("scene", StringType, true),
StructField("cycle", StringType, true)
))
// 转换为df
val test_data_df = spark.createDataFrame(test_data_rdd, structType)
test_data_df.createOrReplaceTempView("test_data_df")
// 拼接周期
val scene_ws = spark.sql("select scene,concat_ws(',',collect_set(cycle)) as cycles from test_data_df group by scene")
scene_ws.count()
scene_ws.show()
scene_ws.createOrReplaceTempView("scene_ws")
/**
* 定义参数确定N的大小,暂定为1
*/
val sum = 1
// 创建广播变量,把N的大小广播出去
val broadcast = sc.broadcast(sum)
/**
* 定义Udf实现获取组内的前N个数据
*/
spark.udf.register("getTopN", (cycles : String) => {
val sum = broadcast.value
var mid = ""
if(cycles.contains(",")){ // 多值
val cycle = cycles.split(",").sorted.reverse // 降序排序
val min = Math.min(cycle.length, sum)
for(i <- 0 until min){
if(mid.equals("")){
mid = cycle(i)
}else{
mid += "," + cycle(i)
}
}
}else{ // 单值
mid = cycles
}
mid
}) val result = spark.sql("select scene,getTopN(cycles) cycles from scene_ws")
result.show()
spark.stop()
}
}

三.结果

  

  

四.备注

  当N大于1时,多个数据会拼接在一起,若想每个一行,可是使用使用列转行功能,参考我的博客:https://www.cnblogs.com/yszd/p/11266552.html

Spark实现分组TopN的更多相关文章

  1. 020 Spark中分组后的TopN,以及Spark的优化(重点)

    一:准备 1.源数据 2.上传数据 二:TopN程序编码 1.程序 package com.ibeifeng.bigdata.spark.core import java.util.concurren ...

  2. 大数据学习day29-----spark09-------1. 练习: 统计店铺按月份的销售额和累计到该月的总销售额(SQL, DSL,RDD) 2. 分组topN的实现(row_number(), rank(), dense_rank()方法的区别)3. spark自定义函数-UDF

    1. 练习 数据: (1)需求1:统计有过连续3天以上销售的店铺有哪些,并且计算出连续三天以上的销售额 第一步:将每天的金额求和(同一天可能会有多个订单) SELECT sid,dt,SUM(mone ...

  3. QL查询案例:取得分组 TOP-N

    [转]SQL查询案例:取得分组 TOP-N CREATE TABLE TopnTest ( name     VARCHAR(10),   --姓名 procDate DATETIME,       ...

  4. 用Spark完成复杂TopN计算的两种逻辑

    如果有商品品类的数据pairRDD(categoryId,clickCount_orderCount_payCount),用Spark完成Top5,你会怎么做? 这里假设使用Java语言进行编写,那么 ...

  5. 取分组TOPN好理解案例

  6. 分别使用Hadoop和Spark实现TopN(1)——唯一键

    0.简介 TopN算法是一个经典的算法,由于每个map都只是实现了本地的TopN算法,而假设map有M个,在归约的阶段只有M x N个,这个结果是可以接受的并不会造成性能瓶颈. 这个TopN算法在ma ...

  7. TopN问题(分别使用Hadoop和Spark实现)

    简介 TopN算法是一个经典的算法,由于每个map都只是实现了本地的TopN算法,而假设map有M个,在归约的阶段只有M x N个,这个结果是可以接受的并不会造成性能瓶颈. 这个TopN算法在map阶 ...

  8. spark面试总结3

    Spark core面试篇03 1.Spark使用parquet文件存储格式能带来哪些好处? 1) 如果说HDFS 是大数据时代分布式文件系统首选标准,那么parquet则是整个大数据时代文件存储格式 ...

  9. Spark面试相关

    Spark Core面试篇01 随着Spark技术在企业中应用越来越广泛,Spark成为大数据开发必须掌握的技能.前期分享了很多关于Spark的学习视频和文章,为了进一步巩固和掌握Spark,在原有s ...

随机推荐

  1. adb连接夜神模拟器与adb常用操作命令

    adb connect 127.0.0.1:62001 adb kill-server 在关闭adb服务后,要使用如下的命令启动adb服务. adb start-servermore than one ...

  2. 新建Springboot项目

    软件为sts软件 1.新建项目 2.工程名称 3.选择依赖项,可以在搜索框中搜索 4.添加端口号 5.创建controller 6.创建controller类,并输入一下内容 package com. ...

  3. Springboot将数据存储到数据库当中

    1.从前端获取数据,同时存储到use当中 public String login(HttpServletRequest request) { User user = new User(); user. ...

  4. day12_7.12递归函数与算法

    一.递归函数 递归函数是在函数的调用阶段直接或间接的调用自己. 于是下面就是一个简单的递归函数: def func(): print('我调我自己') func() func() 然而结果会报错,因为 ...

  5. svn版本库操作(四)

    一.使用命令行模式访问 SVN 服务器 1. 检出(checkout) (1) 首先进入自己的工作目录,例如:D:\svnSpace cd D:\svnSpace (2) 运行 svn checkou ...

  6. Excel-统计函数

    1.Count系列函数 COUNT 数字个数----下面结果为 4 counta 非空的字数 ----下面为6 COUNTBLANK ------非空个数  ---- 下面为9 如何将字符串形式的数字 ...

  7. 数据结构——链队列(linked queue)

    /* linkedQueue.c */ /* 链队列 */ #include <stdio.h> #include <stdlib.h> #include <stdboo ...

  8. 复杂模拟 | 1014 模拟K个同时到来的人在N个窗口,每个窗口只能站M个人的银行排队

    这题我以为还是之前银行排队的思路,但是做着做着就做不下去了了.看了答案我才理解到底是什么个思路. 是这样的:不同于之前排队的题,这里的K个人是同时到来的.所以首先应该让K个人的前N*M(也就是黄线内的 ...

  9. 【CF1097F】Alex and a TV Show

    [CF1097F]Alex and a TV Show 题面 洛谷 题解 我们对于某个集合中的每个\(i\),令\(f(i)\)表示\(i\)作为约数出现次数的奇偶性. 因为只要因为奇偶性只有\(0, ...

  10. [LeetCode] 141. Linked List Cycle 单链表中的环

    Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked lis ...