Spark之RDD,常用的分析算子大全
目录
一、分组聚合算子
groupBy
- 功能:根据指定的函数将 RDD 中的元素进行分组,返回一个新的 RDD,其中每个元素是一个键值对,键是分组的依据,值是一个可迭代的对象,包含该组的所有元素。
- 示例:
-
要求:只有KV类型的RDD才能调用
-
分类:转换算子
-
场景:需要对数据进行分组的场景,或者说分组以后的聚合逻辑比较复杂,不适合用reduce
-
特点:必须经过Shuffle,可以指定新的RDD分区个数,可以指定分区规则
rdd = sc.parallelize([1, 2, 3, 4, 5])
def f(x):
return x % 2
grouped_rdd = rdd.groupBy(f)
result = grouped_rdd.collect()
for key, value in result:
print(f"Key: {key}, Values: {list(value)}")
单词计数
# step1: 读取数据
input_rdd = sc.textFile("../datas/wordcount/word.txt")
# step2: 处理数据
tuple_rdd = ( input_rdd
.filter(lambda line: len(line.strip()) > 0)
.flatMap(lambda line: re.split("\\s+", line))
.map(lambda word: (word, 1))
)
tuple_rdd.foreach(lambda x: print(x))
print("=============================")
# 方案一:groupByKey先分组,再聚合
group_rdd = tuple_rdd.groupByKey()
group_rdd.foreach(lambda x: print(x[0], "------>", *x[1]))
print("=============================")
rs_rdd1 = group_rdd.map(lambda x: (x[0], sum(x[1])))
rs_rdd1.foreach(lambda rs: print(rs))
reduceByKey
- 功能:在一个由键值对组成的 RDD 上,使用指定的二元函数对具有相同键的值进行聚合操作。这个操作在每个键的分区内先进行局部聚合,然后再在所有分区之间进行全局聚合,相比先
groupBy
再在每个组内聚合更高效。 -
要求:只有KV类型的RDD才能调用
-
分类:转换算子
-
场景:需要对数据进行分组并且聚合的场景【reduce能够实现的聚合】
-
特点:必须经过shuffle,可以执行新的RDD分区个数,可以指定分区规则
- 示例:
rdd = sc.parallelize([(1, 2), (1, 3), (2, 4), (2, 5)])
reduced_rdd = rdd.reduceByKey(lambda x, y: x + y)
result = reduced_rdd.collect()
for key, value in result:
print(f"Key: {key}, Value: {value}")
aggregateByKey
- 功能:与
reduceByKey
类似,但提供了更多的灵活性。它需要提供一个初始值,并且可以分别指定分区内和分区间的聚合函数。 - 示例:
rdd = sc.parallelize([(1, 2), (1, 3), (2, 4), (2, 5)])
initial_value = 0
agg_rdd = rdd.aggregateByKey(initial_value, lambda x, y: x + y, lambda x, y: x + y)
result = agg_rdd.collect()
for key, value in result:
print(f"Key: {key}, Value: {value}")
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pyspark import SparkContext, SparkConf
import os
import re
"""
-------------------------------------------------
Description : TODO:groupByKey 和 reduceByKey算子的使用
SourceFile : 01.pyspark_core_fun_group_agg
Author : Frank
Date : 2022/7/19
-------------------------------------------------
"""
if __name__ == '__main__':
# todo:0-设置系统环境变量:全部换成Linux地址
os.environ['JAVA_HOME'] = '/export/server/jdk'
os.environ['HADOOP_HOME'] = '/export/server/hadoop'
os.environ['PYSPARK_PYTHON'] = '/export/server/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/export/server/anaconda3/bin/python3'
# todo:1-构建SparkContext
conf = SparkConf().setMaster("local[2]").setAppName("Remote Test APP")
sc = SparkContext(conf=conf)
# todo:2-数据处理:读取、转换、保存
# step1: 读取数据
# 读取文件
input_rdd = sc.textFile("../datas/wordcount/word.txt")
# step2: 处理数据
# ETL:先转换为二元组
tuple_rdd = ( input_rdd
# 过滤空行
.filter(lambda line: len(line.strip()) > 0)
# 一行多个单词,变成一行一个单词
.flatMap(lambda line: re.split("\\s+", line))
# 将每个单词变成二元组KV结构
.map(lambda word: (word, 1))
)
tuple_rdd.foreach(lambda x: print(x))
print("========================================")
# 方式一:groupByKey + map: