前言

本文介绍如何在Spark Sql和DataFrame中使用UDF,如何利用UDF给一个表或者一个DataFrame根据需求添加几列,并给出了旧版(Spark1.x)和新版(Spark2.x)完整的代码示例。

关于UDF:UDF:User Defined Function,用户自定义函数

创建测试用DataFrame

spark2.0创建DataFrame

// 构造测试数据,有两个字段、名字和年龄
val userData = Array(("A", ), ("B", ), ("B", ), ("B", )) //创建测试df
val userDF = spark.createDataFrame(userData).toDF("name", "age")
userDF.show
+-----+---+
| name|age|
+-----+---+
| A | 16|
| B | 21|
| C | 14|
| D | 18|
+-----+---+
// 注册一张user表 
userDF.createOrReplaceTempView("user")

spark1.0创建DataFrame

 // 构造测试数据,有两个字段、名字和年龄
val userData = Array(("A", ), ("B", ), ("C", ), ("D", ))
//创建测试df
val userDF = sc.parallelize(userData).toDF("name", "age")
// 注册一张user表
userDF.registerTempTable("user")

spark-sql中SQL中UDF用法

1. 通过匿名函数注册UDF

下面的UDF的功能是计算某列的长度,该列的类型为String

// Spark2.x:
spark.udf.register("strLen", (str: String) => str.length()) // Spark1.x:
sqlContext.udf.register("strLen", (str: String) => str.length()) // 仅以Spark2.x为例
spark.sql("select name,strLen(name) as name_len from user").show

2. 通过实名函数注册UDF

实名函数的注册有点不同,要在后面加 _(注意前面有个空格)

// 定义一个实名函数

/**
* 根据年龄大小返回是否成年 成年:true,未成年:false
*/
def isAdult(age: Int) = {
if (age < ) {
false
} else {
true
}
} // 注册(仅以Spark2.x为例)
spark.udf.register("isAdult", isAdult _)

spark-sql中DataFrame中UDF用法

DataFrame的udf方法虽然和Spark Sql的名字一样,但是属于不同的类,它在org.apache.spark.sql.functions里,下面是它的用法

1. 注册

import org.apache.spark.sql.functions._
//方法一:注册自定义函数(通过匿名函数)
val strLen = udf((str: String) => str.length()) //方法二:注册自定义函数(通过实名函数)
val udf_isAdult = udf(isAdult _)

2. 使用

可通过withColumn和select使用,下面的代码已经实现了给user表添加两列的功能 
* 通过看源码,下面的withColumn和select方法Spark2.0.0之后才有的,关于spark1.xDataFrame怎么使用注册好的UDF没有研究

// 通过withColumn添加列
userDF.withColumn("name_len", strLen(col("name"))).withColumn("isAdult", udf_isAdult(col("age"))).show //通过select添加列
userDF.select(col("*"), strLen(col("name")) as "name_len", udf_isAdult(col("age")) as "isAdult").show +-----+---+--------+-------+
| name|age|name_len|isAdult|
+-----+---+--------+-------+
| A | | | false|
| B | | | true|
| C | | | false|
| D | | | true|
+-----+---+--------+-------+

withColumn和select的区别

可通过withColumn的源码看出withColumn的功能是实现增加一列,或者替换一个已存在的列,他会先判断DataFrame里有没有这个列名,如果有的话就会替换掉原来的列,没有的话就用调用select方法增加一列,所以如果我们的需求是增加一列的话,两者实现的功能一样,且最终都是调用select方法,但是withColumn会提前做一些判断处理,所以withColumn的性能不如select好。

注:select方法和sql 里的select一样,如果新增的列名在表里已经存在,那么结果里允许出现两列列名相同但数据不一样,大家可以自己试一下。

参考:https://dongkelun.com/2018/08/02/sparkUDF/

spark自定义函数之——UDF使用详解及代码示例的更多相关文章

  1. spark自定义函数之——UDAF使用详解及代码示例

    UDAF简介 UDAF(User Defined Aggregate Function)即用户定义的聚合函数,聚合函数和普通函数的区别是什么呢,普通函数是接受一行输入产生一个输出,聚合函数是接受一组( ...

  2. laravel 框架配置404等异常页面的方法详解(代码示例)

    本篇文章给大家带来的内容是关于laravel 框架配置404等异常页面的方法详解(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 在Laravel中所有的异常都由Handl ...

  3. Spark 自定义函数(udf,udaf)

    Spark 版本 2.3 文中测试数据(json) {"name":"lillcol", "age":24,"ip":& ...

  4. php自定义函数call_user_func和call_user_func_array详解

    看UCenter的时候有一个函数call_user_func,百思不得其解,因为我以为是自己定义的函数,结果到处都找不到,后来百度了一下才知道call_user_func是内置函 call_user_ ...

  5. c/c++中define用法详解及代码示例

    https://blog.csdn.net/u012611878/article/details/52534622   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...

  6. PCA 降维算法详解 以及代码示例

    转载地址:http://blog.csdn.net/watkinsong/article/details/38536463 1. 前言 PCA : principal component analys ...

  7. 大数据学习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 ...

  8. JS函数动作分层结构详解及Document.getElementById 释义 js及cs数据类型区别 事件 函数 变量 script标签 var function

    html +css 静态页面 js     动态 交互   原理: js就是修改样式, 比如弹出一个对话框. 弹出的过程就是这个框由disable 变成display:enable. 又或者当鼠标指向 ...

  9. Wordpress菜单函数wp_nav_menu各参数详解及示例

    Wordpress菜单函数wp_nav_menu各参数详解及示例   注册菜单 首先要注册菜单,将以下函数添加至function.php函数里   register_nav_menus(array( ...

随机推荐

  1. Python语法基础03(if语句,while循环与for循环)

    if语句:语法:单分支if 判断条件:语句块 执行过程:首先执行判断条件,当条件成立则执行判断条件下面的语句块,若条件不成立,则不执行 双分支if 判断条件:语句块1else:语句块2执行过程: 首先 ...

  2. 关闭windows的DEP

    1.与开启dep时一样,按组合键win+r打开运行窗口,输入cmd并按回车,如图所示:    2.调出命令提示符窗口后,输入bcdedit.exe/set {current} nx AlwaysOff ...

  3. java IO 流小结

    java IO 流小结 java流类图结构 流的分类 按方向 输入流 输出流 按类型 字节流 字符流 结论:只要是处理纯文本数据,就优先考虑使用字符流. 除此之外都使用字节流.

  4. java8的正确使用姿势

    ackage com.expgiga.Java8; import java.util.ArrayList; import java.util.Arrays; import java.util.List ...

  5. tomcat 相关异常

    端口没有被占用却提示Several ports (8005, 8080, 8009) required by Tomcat??? 解决办法:1.运行cmd进入命令行界面:2.运行命令: netsh w ...

  6. Leetcode刷题——007.整数反转

    上代码: #include <cmath> class Solution { public: int reverse(int x) { ; long long tx=llabs(x); ) ...

  7. Linux内存管理(深入理解Linux内核)

    Linux的内存管理,实际上是借助80x86的硬件分段和分页电路,将逻辑地址转化为物理地址的. 物理内存中,有一部分是一直(Permanently)映射给内核使用的,这部分主要用于保存内核的代码,以及 ...

  8. spring 声明式事务原理解读

    在Spring中,声明式事务是通过事务属性(transaction attribute)来定义的.事务属性描述了事务策略如何应用到方法上.事务属性包含5个方面:   传播行为   隔离级别   是否只 ...

  9. JS 将对象转换成字符 字符串转换成json对象

    //js对象 var user = { "name": "张学友", "address": "中国香港" }; //将对 ...

  10. Samza系统架构