传送门:
- 视频地址:黑马程序员Spark全套视频教程
- 1.PySpark基础入门(一)
- 2.PySpark基础入门(二)
- 3.PySpark核心编程(一)
- 4.PySpark核心编程(二)
- 5.PySaprk——SparkSQL学习(一)
- 6.PySaprk——SparkSQL学习(二)
- 7.Spark综合案例——零售业务统计分析
- 8. Spark3新特性及核心概念(背)
一、SparkSQL函数定义
1. SparkSQL 定义UDF函数
1.1 UDF函数的创建
无论Hive还是SparkSQL分析处理数据时,往往需要使用函数,SparkSQL模块本身自带很多实现公共功能的函数,在pyspark.sql.functions中。SparkSQL与Hive一样支持定义函数:UDF和UDAF,尤其是UDF函数在实际项目中使用最为广泛。回顾Hive中自定义函数有三种类型:
- 第一种:UDF (User-Defined-Function)函数
一对一的关系,输入一个值经过函数以后输出一个值;
在Hive中继承UDF类,方法名称为evaluate,返回值不能为void,其实就是实现一个方法; - 第二种:UDAF (User-Defined Aggregation Function)聚合函数
多对一的关系,输入多个值输出一个值,通常与groupBy联合使用; - 第三种:UDTF (User-Defined Table-Generating Functions)函数
—对多的关系,输入一个值输出多个值(一行变为多行);
用户自定义生成函数,有点像flatMap
在SparkSQL中,目前仅仅支持UDF函数和UDAF函数。目前Python仅支持UDF。SparkSQL定义UDF函数有两种方式:
方式一:sparksession.udf.register()
注册的UDF可以用于DSL和SQL。返回值用于DSL风格,传参内给的名字用于SQL风格。
方式1语法:
udf对象 = sparksession.udf.register(参数1,参数2,参数3)
参数1:UDF名称,可用于SQL风格
参数2:被注册成UDF的方法名
参数3:声明UDF的返回值类型
udf对象: 返回值对象,是一个UDF对象,可用于DSL风格
#!usr/bin/env python
# -*- coding:utf-8 -*-
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StringType, IntegerType
import pandas as pd
from pyspark.sql import functions as F
if __name__ == '__main__':
# 0.构建SparkSession执行环境入口对象
spark = SparkSession.builder. \
appName('test'). \
master('local[*]'). \
config("spark.sql.shuffle.partitions", 2). \
getOrCreate()
sc = spark.sparkContext
# 构建RDD
rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7]).map(lambda x: [x])
df = rdd.toDF(['num'])
# TODO 1:方式1:sparksession.udf.register(),DSL和SQL风格均可以使用
# UDF的处理函数
def num_ride_10(num):
return num * 10
# 参数1:注册的UDF名称,这UDF名称可以用于SQL风格
# 参数2:UDF的处理逻辑,是一个单独的方法
# 参数3:UDF的返回值类型
# 注意:UDF注册时候,会声明返回值类型,并且UDF的真实返回值一定要和声明的返回值一致
# 返回值对象:这是一个UDF对象,既可以用于DSL语法
# 当前这种方式定义的UDF,可以通过参数1的名称用于SQL风格,通过返回值对象用于DSL风格
udf2 = spark.udf.register('udf1', num_ride_10, IntegerType())
# SQL风格中使用
# selectExpr以SELECT的表达式执行,
# select方法,接受普通的字符串字段名,或者返回值是Column对象的计算
df.selectExpr('udf1(num)').show()
# DSL风格中使用
# 返回值UDF对象,如果作为方法使用,传入的参数一定是Column对象。
df.select(udf2(df['num'])).show()
+---------+
|udf1(num)|
+---------+
| 10|
| 20|
| 30|
| 40|
| 50|
| 60|
| 70|
+---------+
+---------+
|udf1(num)|
+---------+
| 10|
| 20|
| 30|
| 40|
| 50|
| 60|
| 70|
+---------+
方式二:pyspark.sql.functions.udf
仅能用于DSL风格
方式2语法:
udf对象 = F.udf(参数1, 参数2)
参数1:被注册成UDF的方法名
参数2:声明UDF的返回值类型
udf对象: 返回值对象,是一个UDF对象,可用于DSL风格
#!usr/bin/env python
# -*- coding:utf-8 -*-
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StringType, IntegerType
import pandas as pd
from pyspark.sql import functions as F
if __name__ == '__main__':
# 0.构建SparkSession执行环境入口对象
spark = SparkSession.builder. \
appName('test'). \
master('local[*]'). \
config("spark.sql.shuffle.partitions", 2). \
getOrCreate()
sc = spark.sparkContext
# 构建RDD
rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7]).map(lambda x: [x])
df = rdd.toDF(['num'])
def num_ride_10(num):
return num * 10
# TODO 2 :方式2注册:pyspark.sql.functions.udf,仅能用于SQL风格
udf3 = F.udf(num_ride_10, IntegerType())
df.select(udf3(df['num'])).show()
+----------------+
|num_ride_10(num)|
+----------------+
| 10|
| 20|
| 30|
| 40|
| 50|
| 60|
| 70|
+----------------+
使用UDF两种方式的注册均可以。唯一需要注意的就是:返回值类型—定要有合适的类型来声明。
- 返回int可以用IntergerType
- 返回值小数,可以用FolatType或者DoubleType
- 返回数组list可用ArrayType描述
- 返回字典可用StructType描述
这些Spark内置的数据类型均存储在:
pyspark.sql.types
包中。
1.2 注册返回值是数组类型的UDF
注册一个ArrayType(数字\list)类型的返回值UDF。
注意:数组或者list类型,可以使用spark的 ArrayType来描述即可。
注意:声明ArrayType要类似这样: ArrayType(StringType( ) ),在ArrayType中传入数组内的数据类型
# coding:utf8
import time
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StringType, IntegerType, ArrayType
import pandas as pd
from pyspark.sql import functions as F
if __name__ == '__main__':
# 0. 构建执行环境入口对象SparkSession
spark = SparkSession.builder.\
appName("test").\
master("local[*]").\
config("spark.sql.shuffle.partitions", 2).\
getOrCreate()
sc = spark.sparkContext
# 构建一个RDD
rdd = sc.parallelize([["hadoop spark flink"], ["hadoop flink java"]])
df = rdd.toDF(["line"])
# 注册UDF, UDF的执行函数定义
def split_line(data):
return<