pyspark-03 UDF和Pandas_UDF

本文介绍了PySpark中处理数据的两种自定义函数:UDF(用户定义函数)和Pandas_UDF。UDF针对单行数据操作,而Pandas_UDF则作用于Series,支持更高效的列级操作。通过示例展示了如何定义和应用这些函数,包括计算平方根、计算平均值差和进行模型预测。Pandas_UDF在效率和模型预测方面具有优势。

目录


udf

pyspark里面常常需要自定义函数进行数据处理

  1. udf是针对一行数据进行处理
  2. pandas_udf是针对一个series进行处理
  3. udfa是针对groupby之后的数据进行处理

应用类似于pandas里面的apply函数,

import numpy as np
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from pyspark.sql.types import StringType, FloatType

pandas_df = pd.DataFrame({
   
   'row_number': np.arange(100000)})
spark_df = spark.createDataFrame(pandas_df) 
spark_df.show(5)
+----------+
|row_number|
+----------+
|         0|
|         1|
|         2|
|         3|
|         4|
+----------+

# 定义udf函数,开根号
@F.udf(returnType=FloatType())
def cacl_sqrt(x):
    return float(np.sqrt(x))
 spark_df.withColumn('a2', cacl_sqrt('row_number')).show()
 
 +----------+---------+
|row_number|       a2|
+----------+---------+
|         0|      0.0|
|         1|      1.0|
|         2|1.4142135|
|         3|1.7320508|
|         4|      2.0|

  • udf传入的参数x,就是row_number列里每一行数据
  • udf默认返回是string,returnType建议指定好返回类型
  • udf不支持numpy格式数据,需要转为基本类型float(np.sqrt(x))

聚合后结合collect_list使用udf,实现udaf功能

rdd = spark.sparkContext.parallelize([
    (1, 2., 'sdsd|sdsd:sdsd', date(2000, 1, 1), datetime(2000, 1, 1, 12, 0)),
    (1, 3., '20202_19001', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
    (1, 3., '20202_19001', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
    (1, 3., '20202_19001', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
    (1, 3., '20202_19001', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
  
PySpark 中,`udf` `pandas_udf` 是用于定义用户自定义函数(User Defined Functions, UDF)的两种方式,它们适用于不同的场景并具有不同的性能特征。 ### `udf` 的特点 `udf` 是 PySpark SQL 中最基础的 UDF 类型,它允许用户将 Python 函数注册为 Spark SQL 函数,并在 DataFrame 或 SQL 查询中使用。`udf` 的输入输出是基于行的,每次处理一行数据。这意味着每个函数调用都涉及 JVM Python 之间的通信开销,因此在处理大量数据时效率较低。 - **输入输出类型**:单个值或行数据。 - **执行方式**:按行处理。 - **性能**:由于每次调用处理一行,函数调用次数多,因此性能相对较低。 - **适用场景**:适用于轻量级计算或数据量较小的情况。 ### `pandas_udf` 的特点 `pandas_udf` 是在 Spark 2.3 中引入的,它基于 Apache Arrow,支持使用 Pandas Series 或 DataFrame 作为输入输出类型。`pandas_udf` 的关键优势在于其性能,因为它能够批量处理数据,减少了 JVM Python 之间的通信开销。 - **输入输出类型**:Pandas Series 或 DataFrame。 - **执行方式**:按批次处理,利用 Arrow 的内存格式进行高效数据传输。 - **性能**:显著优于传统 `udf`,特别是在处理大规模数据时。 - **适用场景**:适用于需要高性能处理的复杂计算,例如机器学习特征工程、数据清洗等。 ### 使用示例 #### `udf` 示例 定义一个简单的 UDF 来将字符串转换为大写: ```python from pyspark.sql.functions import udf def to_upper(s): return s.upper() upper_udf = udf(to_upper, StringType()) df = spark.createDataFrame([("hello",), ("world",)], ["text"]) df.withColumn("upper_text", upper_udf(df["text"])).show() ``` #### `pandas_udf` 示例 使用 `pandas_udf` 对数据进行批量处理,例如计算每组的平均值: ```python from pyspark.sql.functions import pandas_udf import pandas as pd # 定义一个 pandas_udf 函数 @pandas_udf('double') def mean_udf(s: pd.Series) -> float: return s.mean() # 创建一个 DataFrame df = spark.createDataFrame([(1, 1.0), (1, 2.0), (2, 3.0), (2, 4.0)], ["id", "value"]) # 应用 pandas_udf df.groupby("id").agg(mean_udf(df["value"]).alias("mean_value")).show() ``` ### 总结 | 特性 | `udf` | `pandas_udf` | |------------------|----------------------------------|---------------------------------------| | 数据处理方式 | 按行处理 | 按批次处理 | | 输入输出类型 | 单个值或行数据 | Pandas Series 或 DataFrame | | 性能 | 相对较低 | 高性能,适合大规模数据 | | 适用场景 | 简单计算或小规模数据 | 复杂计算或大规模数据 | | 是否支持类型提示 | 否 | 是,支持类型提示 | 通过合理选择 `udf` 或 `pandas_udf`,可以显著提高 PySpark 作业的性能效率[^3]。 ```python from pyspark.sql.functions import pandas_udf import pandas as pd # 定义一个 pandas_udf 函数 @pandas_udf('double') def mean_udf(s: pd.Series) -> float: return s.mean() # 创建一个 DataFrame df = spark.createDataFrame([(1, 1.0), (1, 2.0), (2, 3.0), (2, 4.0)], ["id", "value"]) # 应用 pandas_udf df.groupby("id").agg(mean_udf(df["value"]).alias("mean_value")).show() ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值