SparkSQL中UDAF案例分析

JavaSpark | SparkSQL | 创建DataSet | UDF与UDAF | 开窗函数 JavaSpark中sparkSQL的笔记 阅读详情

SparkSQL中UDAF案例分析

1、统计单词的个数

package com.bynear.spark_sql;

import org.apache.spark.sql.Row;
import org.apache.spark.sql.expressions.MutableAggregationBuffer;
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import java.util.ArrayList;


public class Spark_UDAF extends UserDefinedAggregateFunction {
    /**
     * inputSchema指的是输入的数据类型
     *
     * @return
     */
    @Override
    public StructType inputSchema() {
        ArrayList<StructField> fields = new ArrayList<StructField>();
        fields.add(DataTypes.createStructField("str", DataTypes.StringType, true));
        return DataTypes.createStructType(fields);
    }

    /**
     * bufferSchema指的是  中间进行聚合时  所处理的数据类型
     *
     * @return
     */
    @Override
    public StructType bufferSchema() {
        ArrayList<StructField> fields = new ArrayList<StructField>();
        fields.add(DataTypes.createStructField("count", DataTypes.IntegerType, true));
        return DataTypes.createStructType(fields);
    }

    /**
     * dataType指的是函数返回值的类型
     *
     * @return
     */
    @Override
    public DataType dataType() {
        return DataTypes.IntegerType;
    }

    /**
     * 一致性检验,如果为true,那么输入不变的情况下计算的结果也是不变的。
     *
     * @return
     */
    @Override
    public boolean deterministic() {
        return true;
    }

    /**
     * 设置聚合中间buffer的初始值,但需要保证这个语义:两个初始buffer调用下面实现的merge方法后也应该为初始buffer
     * 即如果你初始值是1,然后你merge是执行一个相加的动作,两个初始buffer合并之后等于2,
     * 不会等于初始buffer了。这样的初始值就是有问题的,所以初始值也叫"zero value"
     * 为每个分组的数据执行初始化操作
     *
     * @param buffer
     */
    @Override
    public void initialize(MutableAggregationBuffer buffer) {
        buffer.update(0, 0);
    }

    /**
     * 用输入数据input更新buffer值,类似于combineByKey
     * 指的是,每个分组,有新的值进来的时候,如何进行分组对应的聚合值的计算
     *
     * @param buffer
     * @param input
     */
    @Override
    public void update(MutableAggregationBuffer buffer, Row input) {
        buffer.update(0, Integer.valueOf(buffer.getAs(0).toString()) + 1);
    }

    /**
     * 合并两个buffer,将buffer2合并到buffer1.在合并两个分区聚合结果的时候会被用到,类似于reduceByKey
     * 这里要注意该方法没有返回值,在实现的时候是把buffer2合并到buffer1中去,你需要实现这个合并细节
     * 由于spark是分布式的,所以每一分组的数据,可能会在不同的节点上进行局部聚合,就是update
     * 但是 最后一个分组,在各个节点上的聚合值,要进行merge 也就是合并
     *
     * @param buffer1
     * @param buffer2
     */
    @Override
    public void merge(MutableAggregationBuffer buffer1, Row buffer2) {
        buffer1.update(0, Integer.valueOf(buffer1.getAs(0).toString()) + Integer.valueOf(buffer2.getAs(0).toString()));
    }

    /**
     * 只的是 一个分组的聚合值,如何通过中间的缓存聚合值,最后返回一个最终的聚合值
     *
     * @param buffer
     * @return
     */
    @Override
    public Object evaluate(Row buffer) {
        return buffer.getInt(0);
    }
}

package com.bynear.spark_sql;

import com.clearspring.analytics.util.Lists;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import java.util.Arrays;
import java.util.List;

public class UDAF {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName("UDAF").setMaster("local");
        JavaSparkContext sc = new JavaSparkContext(conf);
        SQLContext sqlContext = new SQLContext(sc);
        List<String> nameList = Arrays.asList("xiaoming", "xiaoming", "刘德华","古天乐","feifei", "feifei", "feifei", "katong");
        //转换为javaRDD
        JavaRDD<String> nameRDD = sc.parallelize(nameList, 3);
        //转换为JavaRDD<Row>
        JavaRDD<Row> nameRowRDD = nameRDD.map(new Function<String, Row>() {
            public Row call(String name) throws Exception {
                return RowFactory.create(name);
            }
        });
        List<StructField> fields = Lists.newArrayList();
        fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
        StructType structType = DataTypes.createStructType(fields);
        DataFrame namesDF = sqlContext.createDataFrame(nameRowRDD, structType);
        namesDF.registerTempTable("names");
        sqlContext.udf().register("countString", new Spark_UDAF());
        sqlContext.sql("select name,countString(name) as count  from names group by name").show();
        List<Row> rows = sqlContext.sql("select name,countString(name) as count  from names group by name").javaRDD().collect();
        for (Row row : rows) {
            System.out.println(row);
        }
    }
}
运行结果:

+--------+-----+
|    name|count|
+--------+-----+
|  feifei|    3|
|xiaoming|    2|
|     刘德华|    1|
|  katong|    1|
|     古天乐|    1|
+--------+-----+

2、统计某品牌价格的平均值

package com.bynear.spark_sql;

import org.apache.spark.sql.Row;
import org.apache.spark.sql.expressions.MutableAggregationBuffer;
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import java.util.ArrayList;

public class MyUDAF extends UserDefinedAggregateFunction {
    private StructType inputSchema;
    private StructType bufferSchema;

    public MyUDAF() {
        ArrayList<StructField> inputFields = new ArrayList<StructField>();
        inputFields.add(DataTypes.createStructField("inputColumn", DataTypes.DoubleType, true));
        inputSchema = DataTypes.createStructType(inputFields);

        ArrayList<StructField> bufferFields = new ArrayList<StructField>();
        bufferFields.add(DataTypes.createStructField("sum", DataTypes.DoubleType, true));
        bufferFields.add(DataTypes.createStructField("count", DataTypes.DoubleType, true));
        bufferSchema = DataTypes.createStructType(bufferFields);
    }

    @Override
    public StructType inputSchema() {
        return inputSchema;
    }

    @Override
    public StructType bufferSchema() {
        return bufferSchema;
    }

    @Override
    public DataType dataType() {
        return DataTypes.DoubleType;
    }

    @Override
    public boolean deterministic() {
        return true;
    }

    @Override
    public void initialize(MutableAggregationBuffer buffer) {
//        缓存区两个分组  分组编号为0 求和sum   初始化值为0
//                     分组编号为1 求count   初始化值为0
        buffer.update(0, 0.0);
        buffer.update(1, 0.0);
    }

    @Override
    public void update(MutableAggregationBuffer buffer, Row input) {
        //如果input的索引值为0的值不为0
        if (!input.isNullAt(0)) {
//            两个分组分别进行更新数据!分组编号0  求和sum  缓存区的值 +  输入放入值
            double updatesum = buffer.getDouble(0) + input.getDouble(0);
//                                 分组编号1  求count  缓存区的个数 + 1
            double updatecount = buffer.getDouble(1) + 1;
            buffer.update(0, updatesum);
            buffer.update(1, updatecount);
        }

    }

    @Override
    public void merge(MutableAggregationBuffer buffer1, Row buffer2) {
        double metgesum = buffer1.getDouble(0) + buffer2.getDouble(0);
        double mergecount = buffer1.getDouble(1) + buffer2.getDouble(1);
        buffer1.update(0, metgesum);
        buffer1.update(1, mergecount);
    }

    @Override
    public Object evaluate(Row buffer) {
        return buffer.getDouble(0) / buffer.getDouble(1);
    }
}

package com.bynear.spark_sql;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.api.java.UDF1;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import java.math.BigDecimal;
import java.util.ArrayList;

public class MyUDAF_SQL {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName("myUDAF").setMaster("local");
        JavaSparkContext jsc = new JavaSparkContext(conf);
        SQLContext sqlContext = new SQLContext(jsc);
        JavaRDD<String> lines = jsc.textFile("C://Users//Administrator//Desktop//fastJSon//sales.txt");
        JavaRDD<Row> map = lines.map(new Function<String, Row>() {
            @Override
            public Row call(String line) throws Exception {
                String[] Linesplit = line.split(",");
                return RowFactory.create(String.valueOf(Linesplit[0]), Double.valueOf(Linesplit[1]));
            }
        });
        ArrayList<StructField> fields = new ArrayList<StructField>();
        fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
        fields.add(DataTypes.createStructField("salary", DataTypes.DoubleType, true));
        StructType structType = DataTypes.createStructType(fields);
        DataFrame df = sqlContext.createDataFrame(map, structType);
        sqlContext.udf().register("myAverage", new MyUDAF());
        df.registerTempTable("zjs_table");

        df.show();

        sqlContext.udf().register("twoDecimal", new UDF1<Double, Double>() {
            @Override
            public Double call(Double in) throws Exception {
                BigDecimal b = new BigDecimal(in);
                double res = b.setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
                return res;
            }
        }, DataTypes.DoubleType);

        DataFrame resultDF = sqlContext.sql("select name,twoDecimal(myAverage(salary)) as 平均值 from zjs_table group by name ");
        resultDF.show();

    }
}

文本:

三星,1542
三星,1548
三星,8456
三星,8866
中兴,1856
中兴,1752
苹果,1500
苹果,2500
苹果,3500
苹果,4500
苹果,5500

运行结果:

+----+-------+
|name| salary|
+----+-------+
|  三星|12345.0|
|  三星| 4521.0|
|  三星| 7895.0|
|  华为| 5421.0|
|  华为| 4521.0|
|  华为| 5648.0|
|  苹果|12548.0|
|  苹果| 7856.0|
|  苹果|45217.0|
|  苹果|89654.0|
+----+-------+

+----+--------+
|name|     平均值|
+----+--------+
|  三星| 8253.67|
|  华为| 5196.67|
|  苹果|38818.75|
+----+--------+

注意点:文本的编码格式,以及Java代码中DataTypes.DoubleType。。。。








Hive UDAF示例 A custom UDAF to group oncatenates all arguments from different rows into a single string. 立即下载

相关推荐

空频、空时、空域、时域、频域抗干扰介绍

1、时域抗干扰:对时间域序列进行滤波,滤波系数h(n),采样序列不断进行输入与滤波系数卷积计算,得到响应输出;例如常用的FIR和IIR滤波器。 对于多窄带干扰噪声源和连续波干扰源有较好的处理效果,还可以解决多径问题; 可以通过在接收机前端处理中增加一个嵌入式块实现; 2、频域抗干扰:接收机不容易受到相对于接收机频带以外的强功率干扰; 通常为带通滤波和阻带滤波, 适用于窄带干扰噪声源,连续波干扰源以及较强的频带外干扰噪声源, 3、空域抗干扰:通过多个自适应天线按照特定组合成天线阵列,波束成形,针对

qq_43517907的博客 7308

Spark编写UDAF自定义函数(JAVA)

maven: org.apache.spark spark-core_2.10 1.6.0 org.apache.spark spark-sql_2.10 1.6.0 org.apache.spark spark-hive_2.10 1.6.0 工具类 --> com.google.guava

ZYJ_2012的博客 3482

maxwell 平面变压器仿真(一)

在学习开关电源设计的时候,我们难免要设计变压器,采用有限元仿真软件MAXWELL 可以帮助我们确定变压器的励磁电感,漏感等参数。对于我们的理论分析大有裨益。但是苦于这破软件的教程真的是相当的零散,我相信大家用起来也总是苦于没有系统的教程指导,撰写本文的目的有两个,一个是记录自己使用的一些问题,一个是给大家提供一个可以参考的文档。

qq_45405656的博客 8252

spark 自定义标准差UDAF

需求是将hive 代码转成spark 代码时 , 需要标准差实现的方式不同 ,hive最后是 /n , spark 的是/n-1 , 因此需要自定义标准差的UDAF , 以下是代码 ,有的判断异常值得情况没做处理 ,可以自行处理 ,因为本人在上游数据源已经做了一次处理,确保了数据的格式不会出现异 import org.apache.commons.lang.StringUtils; imp...

大数据爱好者 562

手机拍照也能玩高光谱?教你用TensorFlow Lite在Android上实现实时RGB转高光谱

本文介绍了如何利用TensorFlow Lite在Android设备上实现实时RGB到高光谱的图像重构技术。通过深度学习模型优化和移动端部署策略,使智能手机具备专业级光谱分析能力,适用于农业检测、化妆品分析等多个领域。

weixin_29091105的博客 247

FastDDS之共享内存

transport层负责为DDS用户数据收发和服务发现提供通信。包含UDP,TCP,SHM。

u010378559的博客 3088

Hive之系统内置函数&自定义函数(UDF、UDAF、UDTF)介绍和案例(附带完整代码)、IDEA运行Hive

1.1 系统内置函数 1.查看系统自带的函数 hive (default)> show functions; 2.显示自带的函数的用法 hive (default)> desc function upper; 3.详细显示自带的函数的用法 hive (default)> desc function extended upper; 1.2 自定义函数 1)Hive 自带了一些函数,比如:max/min 等,但是数量有限(大概二、三百个),自己可以通过自定义 UDF来方便的

Allenzyg的博客 5023

VBA常见错误 - “错误3706,未找到提供程序,该程序可能未正确安装”解决方法

1、问题描述 在利用VBA编程时,引用其它表格数据,出现以下问题: (1)运行“错误3706,未找到提供程序,该程序可能未正确安装”。 (2)引用数据失败 2、解决方法 下载“Access 2010 数据库引擎”,并安装即可。 https://www.microsoft.com/en-us/download/details.aspx?id=54920 AccessDatabaseEngine 2010 官方安装包,官网下载不了的可以来这里下载。(1)运行“错误3706,未找到提..

Nemuel的博客 3万+

104.Spark大型电商项目-各区域热门商品统计-开发自定义UDAF聚合函数之group_concat_distinct()

目录 代码 ConcatLongStringUDF.java GroupConcatDistinctUDAF.java AreaTop3ProductSpark.java 本篇文章记录各区域热门商品统计-开发自定义UDAF聚合函数之group_concat_distinct()。 代码 spark.product ConcatLongStringUDF.java packag...

someby的博客 543

最全教程cadence建立个人CIS数据库

此时如果你删除office365,再装Access数据库,可以安装上,然后你再装office365,系统又会把Access软件给你删除掉,因为冲突了。可以在自己的电脑上新建CIS库,主要包含下面几个内容:数据库文件,原理图封装,PCB封装,数据手册,另外建议做一个器件命名的说明。allegro在调用封装的时候,是看的.psm文件,而不是.dra文件,因此只要是c0402.psm,那么所有的内容都要保持一致。(1)文件夹不要有中文,不要有空格,否则无法识别,可以参考博主的方式,全部使用英文输入法下划线。

D_Katter的博客 254

详解AUTOSAR:专栏总述

本专栏系统介绍AUTOSAR规范及车用控制器软件开发,内容覆盖基础架构、SWC/RTE、通信栈、诊断、存储、安全、看门狗、工具链、环境配置与项目实战,并持续更新各模块的集成机制与工程要点。

不脱发的程序猿 3931

SparkSQL用UDAF实现Bitmap函数

创建测试表使用phoenix在HBase中创建测试表,字段使用VARBINARY类型CREATE TABLE IF NOT EXISTS test_binary ( date VARCHA...

大数据星球-浪尖 1125

【深度解析】解决 NVIDIA 显卡“掉卡”与 Xid 79 错误:开启持久化模式 (Persistence Mode)

【深度解析】解决 NVIDIA 显卡“掉卡”与 Xid 79 错误:开启持久化模式 (Persistence Mode)

LetsonH的博客 870

SparkSQL中UDF和UDAF

UDF: User Defined Function,用户自定义的函数,函数的输入是一条具体的数据记录,实现上讲就是普通的Scala函数; UDAF:User Defined Aggregation Function,用户自定义的聚合函数,函数本身作用于数据集合,能够在聚合操作的基础上进行自定义操作; 实质上讲,例如说UDF会被Spark SQL中的Catalyst封装成为Expression

麒麟 7271

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

SparkSQL 自定义算子UDF、UDAF、UDTF

背景 我根据算子输入输出之间的关系来理解算子分类: UDF——输入一行,输出一行 UDAF——输入多行,输出一行 UDTF——输入一行,输出多行 本文主要是整理这三种自定义算子的具体实现方式 使用的数据集——用户行为日志user_log.csv,csv中自带首行列头信息,字段定义如下: 1. user_id | 买家id 2. item_id | 商品id 3. cat_id | 商品类别...

抛砖引玉 7689

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

sparkSQL 自定义UDAF函数总结

学完了sparkSQL的自定义函数部分,做个总结。也希望能帮到大家,如有错误谢谢指正。 在学习Hive的时候已经了解到当内置函数无法满足业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user defined function) 用户自定义函数类别分为以下三种: 1).UDF:输入一行,返回一个结果(一对一) 上代码 创建DataFrame scala> val df = spark.read.json("data/user.json") df: org.apache.spark.sql

kk阿彬 1037

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【Spark精讲】一文讲透SparkSQL聚合过程以及UDAF开发

【Spark精讲】一文讲透SparkSQL聚合过程以及UDAF开发:SparkSQL聚合过程、PARTIAL1、PARTIAL2、FINAL、COMPLETE

话数Science 1968

SparkSql之UDF、UDAF、UDTF

UDF---------------------------------------- 完整的示例:object SparkSQL { def main(args:Array[String]):Unit = { //创建SparkConf()并设置App名称 val conf = new SparkConf().setAppName("SparkSQLDemo").setMa...

莫慌 吃口药 902

SparkSQL的两种UDAF的讲解

Spark的dataframe提供了通用的聚合方法,比如count(),countDistinct(),avg(),max(),min()等等。然而这些函数是针对data...

大数据星球-浪尖 4894

Sparksql UDAF,UDF详解(转)

(转)https://www.cnblogs.com/xing901022/p/6436161.html Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版) 在Spark中,也支持Hive中的自定义函数。自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date...

fengfengchen95的博客 1517

SparkSQL 自定义函数:UDF与 理解UDAF相关方法

目录 前言: 一:SparkSQL自定义函数的种类 二:UDF实现 三:UDAF实现 四:查看运行结果: 前言: 类似于Hive 当中的自定义函数,SparkSql中同样也可以使用自定义函数来实现新功能。 一:SparkSQL自定义函数的种类 SparkSql自定义函数与Hive中的自定义函数一样分为三类: 1、UDF(User-Defined-Function) ...

小蜜蜂博客 469

SparkSQL用户自定义聚合函数UDAF(新)

说明:UDAF使用的六个步骤,难点在第三步骤,代码中都有注释 1.声明用户自定义聚合函数 2.继承UserDefinedAggregateFunction 3.实现方法 4.创建聚合函数对象 5.注册函数 6.使用函数 本案例实现平均年龄的计算–avg的功能 自定义UDAF函数 //声明函数 //ageAve(age):函数的入参:age class MyAgeAvg extends UserDe...

weixin_43548518的博客 313

使用SparkSQL 和 Hive API 代码实现用户自定义函数UDF UDAF UDTF

UDAF 例:SparkSQL 中继承Aggregator自定义UDAF函数:输入多行,返回一行 => 聚合函数 。 (Scala代码实现) import org.apache.spark.SparkConf import org.apache.spark.sql.expressions.Aggregator import org.apache.spark.sql.{DataFrame, Encoder, Encoders, SparkSession, functions} //输入多行,返回

m0_38109926的博客 1485

SparkSql------自定义函数UDF和UDAF

UDF 测试数据 {"name":"aaa", "age":20} {"name":"bbb", "age":30, "facevalue":80} {"name":"ccc", "age":28, "facevalue":80} {"name":"ddd", "age":28, "facevalue":90} 案例(scala语言) import org.apache.spark....

洛云凡 267

SparkSQL 之 UDF、UDAF 函数代码实现

分类:UDF 一对一 / UDAF 多对一 / UDTF 一对多注册:SQL 用 register,DSL 用 functions.udfUDAF:强类型 Aggregator 优于弱类型 UDAF作者:大数据技术实践者博客GitHub专注 AI Agent · LangGraph · RAG · 大数据架构 · 数据工程实践。

https://starzy1990.github.io/ 465
上一篇: Spark SQL UDF2的使用
下一篇: eq,neq,gt,lt等表达式缩写
JSON_ZJS
博客等级 码龄9年 30粉丝 159原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值