PySpark之SparkSQL定义UDF函数

一、Hive自定义函数类型

  • UDF(User-Defined-Function)函数
    • 一对一的关系,输入一个值经过函数以后输出一个值
    • 在Hive中继承UDF类,方法名称为evaluate,返回值不能为void,其实就是实现一个方法
  • UDAF(User-Defined Aggregation Function) 聚合函数
    • 多对一的关系,输入多个值输出一个值,通常与groupBy联合使用
  • UDTF(User-Defined Table-Generating Functions) 函数
    • 一对多的关系,输入一个值输出多个值(一行变为多行)
    • 用户自定义生成函数,有点像flatMap

二、定义方式

  • sparksession.udf.register()

    • 注册的UDF可以用于DSL和SQL

    • 返回值用于DSL风格,传参内给的名字用于SQL风格

      • udf对象 = sparksession.udf.register(参数1,参数2,参数3)
      • 参数1:UDF名称,可用于SQL风格
      • 参数2:被注册成UDF的方法名
      • 参数3:声明UDF的返回值类型
      • udf对象:返回值对象,是一个UDF对象,可用于DSL风格
  • pyspark.sql.functions.udf

    • 仅能用于DSL风格

      • udf对象 = F.udf(参数1,参数2)
      • 参数1:被注册成UDF的方法名
      • 参数2:声明UDF的返回值类型
      • udf对象:返回值对象,是一个UDF对象,可用于DSL风格
      • 其中
        • F是from pyspark.sql import functions as F
        • 其中,被注册成UDF的方法名是指具体的计算方法,如:def add(x,y):x+y
        • add就是将要被注册成UDF的方法名

三、构建一个Interger返回值类型的UDF

# TODO sparksession.udf.resgiter()注册
# 注册UDF,功能:将数字都乘以10
def num_ride_10(num):
    return num * 10
# 返回值用于DSL风格   内部注册的名称用于SQL(字符串表达式)风格
# 参数1:UDF名称(可用于SQL风格),参数2:UDF的本体方法(处理逻辑),参数3:声明返回值类型
# 返回值可用于DSL
udf2 = spark.udf.register("udf1", num_ride_10,IntegerType())
df.select(udf2(df['num'])).show()
df.selectExpr("udf1(num)").show()

# TDDO pyspark.sql.functions.udf注册,仅能用DSL风格
# 参数1:UDF的本体方法(处理逻辑),参数2:声明返回值类型
udf3 = F.udf(num_ride_10,IntegerType())
df.select(udf3(df['num'])).show()

四、构建一个Float返回值类型

import os
from pyspark.sql import SparkSession
from pyspark.sql.types import FloatType
from pyspark.sql import functions as F

os.environ['SPARK_HOME'] = '/export/server/spark'
PYSPARK_PYTHON = '/root/anaconda3/envs/pyspark_env/bin/python'
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DRIVER_PYTHON'] = PYSPARK_PYTHON

spark = SparkSession.builder.\
    appName("minuproject").\
    master('local[*]').\
    getOrCreate()
sc = spark.sparkContext

rdd = sc.parallelize([1.1,2.2,3.3,4.4,5.5,6.6,7.7]).map(lambda x:[x])
df = rdd.toDF(["num"])
# TODO sparksession.udf.register()方式注册,功能:将数字都乘以10
def num_ride_10(num):
    return num * 10
# 返回值用于DSL风格 内部注册的名称用于SQL(字符串表达式)风格
udf2 = spark.udf.register("udf1",num_ride_10,FloatType())
df.select(udf2(df['num'])).show()
df.selectExpr("udf1(num)").show()
# TODO pyspark.sql.functions.udf
udf3 = F.udf(num_ride_10(),FloatType())
df.select(udf3(df['num'])).show()

五、注册一个ArrayType()类型的返回值UDF

注意:数组或者list类型,可以使用spark的ArrayType来描述即可

注意:声明ArrayType要累死这样:ArrayType(StringType()),在ArrayType中传入数组内的数据类型

from pyspark.sql import SparkSession
import os
from pyspark.sql.types import ArrayType
from pyspark.sql.types import StringType
from pyspark.sql import functions as F

os.environ['SPARK_HOME'] = '/export/server/spark'
PYSPARK_PYTHON = '/root/anaconda3/envs/pyspark_env/bin/python'
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DRIVER_PYTHON'] = PYSPARK_PYTHON

spark = SparkSession.builder.\
    appName("miniproject").\
    master("local[*]").\
    getOrCreate()
sc = spark.sparkContext

rdd = sc.parallelize([["hadoop spark flink"],["hadoop flink java"]])
df = rdd.toDF(["line"])
# TODO spark.udf.register()方式注册
def split_line(line):
    return line.split(" ")
# 返回值用DSL风格,内部注册的名称用于SQL(字符串表达式)风格
udf2 = spark.udf.register("udf1",split_line,ArrayType(StringType()))
df.select(udf2(df['line'])).show()
df.selectExpr("udf1(line)").show()
# TODO pyspark.sql.functions.udf方式注册,仅能使用DSL风格
udf3 = F.udf(split_line,ArrayType(StringType()))
df.select(udf3(df['line'])).show(truncate=False)

六、返回值类型

使用UDF两种方式的注册均可以,唯一需要注意的是:返回值类型一定要有合适的类型来声明

这些Spark内置的数据类型均存储在:pyspark.sql.types包中

返回值声明类型
intIntergerType
小数FolatType或者DoubleType
数组/listArrayType
字典StructType
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值