Spark之pyspark转换函数

RDD转换函数详解

0、前言

 本文列举5个常见的RDD转换函数:

操作 含义
filter(func) 筛选出满足函数func的元素,并返回一个新的数据集
map(func) 将每个元素传递到函数func中,并将结果返回一个新的数据集
flatMap(func) 与map类似,但每个输入元素都可以映射到0个或多个输出结果
groupByKey() 应用于(K, V)键值对的数据集时,返回一个新的(K, Iterable)形式的数据集
reduceByKey(func) 应用于(K, V)键值对的数据集时,返回一个新的(K, V)形式的数据集,其中每个值是将每个key传递到函数func中进行聚合后的结果

1、filter(func)

word.txt:
Hadoop is good
Spark is better
Spark is fast

# sc.textFile('word.txt')是创建RDD对象的一种方式,可以是打开本地文件,可以是打开HDFS文件,也可以是打开云端文件
# 另一种创建RDD对象的方式是并行化数组或集合,eg:sc.parallelize([1, 2, 3, 4, 5])
lines = sc.textFile('word.txt')
linesWithSpark = lines.filter(lambda line : 'Spark' in line)
# collect是动作函数,作用是返回RDD中的数据,以list形式
linesWithSpark.collect()

输出

Spark is better
Spark is fast

2、map(func)

eg1:

rdd1 = sc.parallelize([1, 2, 3, 4, 5])
rdd2 = rdd1.map(lambda x:x + 10)
rdd2.collect()

输出

11
12
13
14
<think> 我们正在处理一个关于PySpark中stack函数的使用方法的查询。根据用户需求,我们需要提供stack函数的使用指南。 首先,我们需要明确stack函数PySpark中的用途。根据PySpark文档,stack函数用于将多列数据转换为行。具体来说,它可以将若干个指定的列按照给定的表达式堆叠成多行。 语法: stack(n, expr1, expr2, ..., expr_k) 参数: n: 表示要堆叠的行数。 随后是n个表达式对(每个表达式对表示新生成行的两列:一列是列名,另一列是值),因此总共有2*n个表达式(不包括第一个参数n)。 实际上,stack函数的参数个数应该是1 + 2*n。第一个参数是整数n,表示要堆叠的行数,然后每两个表达式为一组:第一组表达式表示第一行的列名和值,第二组表示第二行的列名和值,以此类推。 例如: stack(2, 'col1', col1, 'col2', col2) 这个表达式会生成两行,每行有两列。第一行:列名为'col1',值为col1列的值;第二行:列名为'col2',值为col2列的值。 但注意,实际上在PySpark中,stack函数通常用于将多列数据转换为行,并且常用于处理宽表转长表的情况。 下面我们通过一个示例来说明如何使用stack函数。 假设我们有如下DataFrame: +----+----+----+----+ | id | Q1 | Q2 | Q3 | +----+----+----+----+ | 1 | 10 | 20 | 30 | | 2 | 40 | 50 | 60 | +----+----+----+----+ 我们想要将每个季度的数据(Q1, Q2, Q3)转换为两列:一列是季度名称(字符串),另一列是对应的值(整数)。也就是说,我们想要得到: +----+----+----+ | id |quarter|sales| +----+----+----+ | 1 | Q1 | 10 | | 1 | Q2 | 20 | | 1 | Q3 | 30 | | 2 | Q1 | 40 | | 2 | Q2 | 50 | | 2 | Q3 | 60 | +----+----+----+ 我们可以使用stack函数来实现: 步骤: 1. 使用select或者withColumn,结合expr函数(因为stack函数PySpark中通常作为SQL表达式使用)。 2. 在表达式中使用stack函数,并指定要堆叠的列。 具体代码: 首先创建DataFrame: data = [(1, 10, 20, 30), (2, 40, 50, 60)] df = spark.createDataFrame(data, ["id", "Q1", "Q2", "Q3"]) 然后使用selectExpr(或者select+expr): result = df.selectExpr("id", "stack(3, 'Q1', Q1, 'Q2', Q2, 'Q3', Q3) as (quarter, sales)") 注意:这里第一个参数3表示要堆叠3行,然后后面跟着6个表达式:3组,每组两个:一个字符串(季度名称)和一个列(该季度的值)。 这样就会得到上面期望的结果。 另外,我们也可以使用select配合expr函数来实现: from pyspark.sql.functions import expr result = df.select("id", expr("stack(3, 'Q1', Q1, 'Q2', Q2, 'Q3', Q3) as (quarter, sales)")) 注意:stack函数返回的是一个结构(struct)的数组,然后我们使用as关键字将其拆分为两列(quarter和sales)。 但是,如果我们要堆叠的列很多,手动写可能比较麻烦,我们可以考虑使用编程的方式构建表达式字符串。不过,这超出了本指南的范围。 另外,stack函数还可以嵌套使用,但一般情况下,我们使用一次stack就可以完成多列转多行。 注意事项: - stack函数PySpark中是一个SQL函数,因此通常需要在SQL表达式字符串中使用,或者使用expr函数。 - 在堆叠时,每一组表达式(列名和值)的类型必须一致,或者可以转换为一致(例如,列名都是字符串,值都是整数)。 - 堆叠后的列名和类型:列名由as子句指定,类型则由每个值列的类型决定(它们应该相同,否则会尝试强制转换,若失败则报错)。 此外,还有一种方法是使用melt函数,但PySpark没有内置的melt函数,所以通常使用stack来实现类似功能。 现在,我们将使用上面的例子来展示完整的PySpark代码。 完整示例代码: from pyspark.sql import SparkSession spark = SparkSession.builder.appName("StackExample").getOrCreate() # 创建示例DataFrame data = [(1, 10, 20, 30), (2, 40, 50, 60)] columns = ["id", "Q1", "Q2", "Q3"] df = spark.createDataFrame(data, columns) # 使用stack函数 result = df.selectExpr("id", "stack(3, 'Q1', Q1, 'Q2', Q2, 'Q3', Q3) as (quarter, sales)") result.show() 输出: +---+-------+-----+ | id|quarter|sales| +---+-------+-----+ | 1| Q1| 10| | 1| Q2| 20| | 1| Q3| 30| | 2| Q1| 40| | 2| Q2| 50| | 2| Q3| 60| +---+-------+-----+ 这样,我们就成功地将每个季度的列堆叠成了行。 总结:stack函数PySpark中是一个强大的行转换工具,特别适用于将宽格式数据转换为长格式数据(即数据透视的逆操作)。 如果用户需要处理动态列数的情况,可能需要构建动态的stack表达式字符串,这可以通过编程方式实现(例如,根据列名列表生成表达式字符串)。 希望这个指南对您有帮助! </think>### PySpark `stack` 函数使用指南 `stack` 函数用于将多列数据**转换为行**(列转行),是处理宽表变长表的常用工具,适用于数据透视、结构转换等场景。 #### 基本语法 ```python from pyspark.sql import functions as F df.select(F.expr("stack(n, col1_name, col1_val, col2_name, col2_val, ...) as (new_col1, new_col2)")) ``` - **`n`**: 要堆叠的列数量 - **`colX_name`**: 新生成的列名(字符串) - **`colX_val`**: 原始列的值或表达式 - **`(new_col1, new_col2)`**: 定义输出列名 --- #### 示例:季度销售数据转换 **原始数据**: | id | Q1_sales | Q2_sales | Q3_sales | |-----|----------|----------|----------| | 1 | 100 | 200 | 150 | | 2 | 300 | 250 | 400 | **目标**:将季度列转换为行 ```python from pyspark.sql import SparkSession spark = SparkSession.builder.appName("stack_example").getOrCreate() data = [(1, 100, 200, 150), (2, 300, 250, 400)] df = spark.createDataFrame(data, ["id", "Q1_sales", "Q2_sales", "Q3_sales"]) # 使用stack转换 result = df.selectExpr( "id", "stack(3, 'Q1', Q1_sales, 'Q2', Q2_sales, 'Q3', Q3_sales) as (quarter, sales)" ) result.show() ``` **输出**: ``` +---+-------+-----+ | id|quarter|sales| +---+-------+-----+ | 1| Q1| 100| | 1| Q2| 200| | 1| Q3| 150| | 2| Q1| 300| | 2| Q2| 250| | 2| Q3| 400| +---+-------+-----+ ``` --- #### 关键特性 1. **动态列处理** 支持动态生成行,每行包含固定数量的新列(示例中生成两列:`quarter` 和 `sales`)。 2. **类型安全** 所有 `colX_val` 必须有兼容的数据类型(如统一为整数或字符串)。 3. **嵌套使用** 可结合其他函数实现复杂转换: ```python df.selectExpr( "id", "stack(2, 'min', min_value, 'max', max_value) as (metric, value)", "year" # 保留其他列 ) ``` --- #### 常见问题解决 1. **列名动态生成** 若列名需动态计算,使用 `concat` 函数: ```python df.selectExpr( "id", "stack(3, concat('Q', '1'), Q1_sales, ...)" ) ``` 2. **处理空值** 用 `coalesce` 替换 NULL: ```python "stack(3, 'Q1', coalesce(Q1_sales, 0), ...)" ``` 3. **性能优化** - 避免在 `stack` 中使用 UDF - 提前过滤无用列减少数据量 --- #### 应用场景 1. 将多指标宽表转为长表(适合可视化工具) 2. 数据标准化预处理 3. 时间序列维度转换(如季度→月度) 4. 机器学习特征工程中的结构重组 > 参考官方文档:[PySpark SQL Functions](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/functions.html) [^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值