一、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的方法名
- F是
-
三、构建一个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
包中
返回值 | 声明类型 |
---|---|
int | IntergerType |
小数 | FolatType或者DoubleType |
数组/list | ArrayType |
字典 | StructType |