PySpark 常用算子详解

PySpark 提供了丰富的算子用于分布式数据处理,主要分为转换算子 (Transformations)和行动算子(Actions)。转换算子用于创建新的 RDD 或 DataFrame,而行动算子触发实际的计算并返回结果。

一、RDD 常用算子

1. 转换算子

转换算子是惰性的,不会立即执行,而是构建计算图。

1.1 基本转换
  • map(func)

    对 RDD 中的每个元素应用函数func

    复制代码
    rdd = sc.parallelize([1, 2, 3])
    squared = rdd.map(lambda x: x**2)  # [1, 4, 9]
  • filter(func)

    过滤出满足函数func条件的元素。

    复制代码
    even_nums = rdd.filter(lambda x: x % 2 == 0)  # [2]
  • flatMap(func)

    先应用func,再将结果展平。

    复制代码
    words = sc.parallelize(["Hello world", "Spark is fast"])
    flat_words = words.flatMap(lambda x: x.split())  # ["Hello", "world", "Spark", "is", "fast"]
1.2 集合操作
  • union(other)

    合并两个 RDD。

    复制代码
    rdd1 = sc.parallelize([1, 2])
    rdd2 = sc.parallelize([3, 4])
    union_rdd = rdd1.union(rdd2)  # [1, 2, 3, 4]
  • intersection(other)

    返回两个 RDD 的交集。

    复制代码
    rdd1 = sc.parallelize([1, 2, 3])
    rdd2 = sc.parallelize([3, 4, 5])
    intersect_rdd = rdd1.intersection(rdd2)  # [3]
  • distinct()

    去重。

    复制代码
    rdd = sc.parallelize([1, 1, 2, 2, 3])
    distinct_rdd = rdd.distinct()  # [1, 2, 3]
1.3 键值对操作
  • groupByKey()

    按键分组。

    复制代码
    pairs = sc.parallelize([("a", 1), ("a", 2), ("b", 3)])
    grouped = pairs.groupByKey()  # [("a", [1, 2]), ("b", [3])]
  • reduceByKey(func)

    按键聚合值。

    复制代码
    summed = pairs.reduceByKey(lambda x, y: x + y)  # [("a", 3), ("b", 3)]
  • join(other)

    键值对 RDD 的内连接。

    复制代码
    rdd1 = sc.parallelize([("a", 1), ("b", 2)])
    rdd2 = sc.parallelize([("a", 3), ("a", 4)])
    joined = rdd1.join(rdd2)  # [("a", (1, 3)), ("a", (1, 4))]
2. 行动算子

行动算子触发计算并返回结果或写入外部存储。

2.1 基本行动
  • collect()

    将 RDD 的所有元素收集到驱动程序。

    复制代码
    rdd = sc.parallelize([1, 2, 3])
    result = rdd.collect()  # [1, 2, 3]
  • count()

    返回 RDD 的元素个数。

    复制代码
    count = rdd.count()  # 3
  • take(n)

    返回 RDD 的前 n 个元素。

    复制代码
    first_two = rdd.take(2)  # [1, 2]
  • reduce(func)

    使用函数func聚合 RDD 元素。

    复制代码
    total = rdd.reduce(lambda x, y: x + y)  # 6
2.2 保存操作
  • saveAsTextFile(path)
    将 RDD 保存为文本文件。

    复制代码
    rdd.saveAsTextFile("hdfs://path/to/output")

二、DataFrame 常用算子

1. 转换算子

DataFrame 的转换算子基于关系代数,支持 SQL 风格操作。

1.1 选择与过滤
  • select(cols)

    选择列。

    复制代码
    df.select("name", "age").show()
  • filter(condition)

    过滤行。

    复制代码
    df.filter(df["age"] > 20).show()
  • where(condition)

    等价于filter

    复制代码
    df.where("age > 20").show()
1.2 聚合操作
  • groupBy(cols)

    按列分组。

    复制代码
    df.groupBy("department").avg("salary").show()
  • agg(expressions)

    自定义聚合。

    复制代码
    from pyspark.sql.functions import sum, avg
    df.agg(sum("sales"), avg("age")).show()
1.3 连接操作
  • join(other, on, how)
    连接两个 DataFrame。

    复制代码
    df1.join(df2, on="id", how="inner").show()
1.4 排序与去重
  • sort(cols)

    排序。

    复制代码
    df.sort("age", ascending=False).show()
  • dropDuplicates(subset)

    去重。

    复制代码
    df.dropDuplicates(["name", "age"]).show()
2. 行动算子
  • show(n)

    显示前 n 行。

    复制代码
    df.show(5)
  • count()

    统计行数。

    复制代码
    rows = df.count()
  • collect()

    收集所有行到驱动程序。

    复制代码
    data = df.collect()
  • toPandas()

    转换为 Pandas DataFrame。

    复制代码
    pandas_df = df.toPandas()

三、SQL 函数

PySpark 提供了丰富的 SQL 函数,用于复杂的数据处理。

1. 数学函数
  • sum(), avg(), max(), min(), count()
  • round(), sqrt(), log(), exp()
2. 字符串函数
  • concat(), substring(), lower(), upper(), trim()
  • split(), regexp_replace()
3. 日期时间函数
  • current_date(), current_timestamp()
  • date_format(), year(), month(), dayofmonth()
4. 条件函数
  • when(), otherwise()
  • ifnull(), coalesce()

示例:

复制代码
from pyspark.sql.functions import when, col

df.withColumn("age_group", 
             when(col("age") < 18, "minor")
             .when(col("age") < 60, "adult")
             .otherwise("senior"))

四、窗口函数

窗口函数允许在特定行组上执行计算,无需分组。

复制代码
from pyspark.sql.window import Window
from pyspark.sql.functions import rank, row_number

window_spec = Window.partitionBy("department").orderBy("salary")

# 添加排名列
df.withColumn("rank", rank().over(window_spec)).show()

五、算子执行顺序

PySpark 采用惰性计算

  1. 转换算子构建 DAG(有向无环图)
  2. 行动算子触发 DAG 的执行
  3. 中间结果可能被缓存(使用cache()persist()

示例:

复制代码
rdd = sc.parallelize([1, 2, 3, 4])
rdd = rdd.map(lambda x: x**2).filter(lambda x: x > 5)  # 转换
result = rdd.collect()  # 行动,触发计算

六、性能优化建议

  1. 避免使用collect():仅用于小数据结果,大数据会导致驱动程序内存溢出
  2. 使用广播变量:将小表广播到所有 Executor,减少 Shuffle
  3. 合理分区 :通过repartition()coalesce()调整分区数
  4. 缓存重用数据 :对需要多次使用的 RDD 或 DataFrame 使用cache()
  5. 优先使用 DataFrame:比 RDD 更高效(基于 Catalyst 优化器)

通过掌握这些算子,你可以高效地处理和分析大规模数据集。在实际应用中,建议结合具体业务场景选择合适的算子,并注意性能调优。

相关推荐
不辉放弃20 小时前
PySpark Standalone 集群
pyspark·大数据开发
不辉放弃20 小时前
pyspark中map算子和flatmap算子
数据库·pyspark·大数据开发
贝塔西塔4 天前
PySpark中python环境打包和JAR包依赖
大数据·开发语言·python·spark·jar·pyspark
SLUMBER_PARTY_11 天前
pyspark大规模数据加解密优化实践
pyspark·pandas_udf
SLUMBER_PARTY_1 个月前
pyspark非安装使用graphframes
pyspark
SLUMBER_PARTY_1 个月前
PySpark 使用pyarrow指定版本
pyspark
不辉放弃1 个月前
HiveSQL语法全解析与实战指南
数据库·hive·大数据开发
不辉放弃2 个月前
HDFS:解锁大数据存储的奥秘
数据库·大数据开发
Francek Chen3 个月前
【PySpark大数据分析概述】03 PySpark大数据分析
大数据·分布式·数据挖掘·数据分析·pyspark