通过PySpark单词计数案例带你学习map、flatMap、reduceByKey方法(Python)

文本文件:通过PySpark单词计数案例带你学习map、flatMap、reduceByKey方法(Python)资源-CSDN下载


一、题目要求

请使用 PySpark 完成一个单词计数程序,具体要求如下:

  1. 配置并初始化 Spark 执行环境
  2. 读取本地文件 "D:/test1.txt"
  3. 对文件内容进行单词拆分
  4. 将每个单词转换为 (单词,1) 的二元元组形式
  5. 对相同单词进行分组并计算出现次数
  6. 输出最终的单词计数结果

二、实现代码:

#1.构建执行环境入口对象
from pyspark import SparkConf, SparkContext
import os
os.environ['PYSPARK_PYTHON'] = "E:/Python/Python3.10.4/python.exe"
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
#2.读取文件
rdd = sc.textFile("D:/test1.txt")
#3.取出全部单词
word_rdd = rdd.flatMap(lambda x: x.split())
#4.将所有单词都转换成二元元组,单词为Key,value设置为1
#(spark,1)
word_with_one_rdd = word_rdd.map(lambda word:(word,1))
#5.分组并求和
result_rdd = word_with_one_rdd.reduceByKey(lambda a,b:a+b)
#6.打印输出
print(result_rdd.collect())

三、实现效果图:


四、三个RDD转换算子讲解

在这段 PySpark 单词计数代码中,map()flatMap()reduceByKey()是三个核心的 RDD 转换算子。


1、map () 方法:一对一映射转换

1.核心原理

map() 是最基础的转换算子,它对 RDD 中的每个元素独立应用一个函数,每个元素都会被转换为一个新元素,最终生成一个新的 RDD。

2.关键特点

  • 输入输出数量一致:原始 RDD 有 N 个元素,转换后仍有 N 个元素
  • 转换独立性:每个元素的转换不影响其他元素
  • 函数灵活性:可以返回任意类型的结果(与输入类型可不同)
word_with_one_rdd = word_rdd.map(lambda word: (word, 1))

假设 word_rdd 中的元素是:["spark", "hadoop", "spark"]
经过 map() 转换后:

  • 第一个元素 "spark" → ("spark", 1)
  • 第二个元素 "hadoop" → ("hadoop", 1)
  • 第三个元素 "spark" → ("spark", 1)
    最终 word_with_one_rdd 的元素为:[("spark", 1), ("hadoop", 1), ("spark", 1)]

3.更多示例

# 示例1:数字翻倍
nums = sc.parallelize([1, 2, 3, 4])
doubled = nums.map(lambda x: x * 2)  # 结果: [2, 4, 6, 8]

# 示例2:字符串长度计算
words = sc.parallelize(["apple", "banana", "cat"])
lengths = words.map(lambda s: len(s))  # 结果: [5, 6, 3]

2、flatMap () 方法:先映射后扁平化

1.核心原理

flatMap() 可以理解为 map () + 扁平化 的组合操作:

  1. 先对每个元素应用映射函数(同 map ()),生成一个集合 / 列表
  2. 再将所有集合 / 列表 "摊平",把其中的元素逐个提取出来作为新 RDD 的元素

2.关键特点

  • 输入输出数量可变化:1 个元素可生成 0 到多个元素
  • 扁平化处理:会自动解除嵌套结构(将列表中的元素 "拉平")
  • 适合拆分操作:尤其适合文本拆分、数据展开等场景
word_rdd = rdd.flatMap(lambda x: x.split())

假设 rdd 中的元素是两行文本:["hello spark", "hello hadoop"]
处理过程:

  1. 第一步(类似 map):
    • 第一行 "hello spark" → 拆分为 ["hello", "spark"]
    • 第二行 "hello hadoop" → 拆分为 ["hello", "hadoop"]
  2. 第二步(扁平化):将两个列表合并为一个列表
    最终 word_rdd 的元素为:["hello", "spark", "hello", "hadoop"]

3.与 map () 的对比

如果用 map() 处理上述文本:

# 用map()的结果(未扁平化)
map_result = rdd.map(lambda x: x.split())
# 结果: [["hello", "spark"], ["hello", "hadoop"]] (仍是嵌套列表)

这正是 flatMap() 与 map() 的核心区别:flatMap() 会移除一层嵌套结构。

4.更多示例

# 示例1:将句子拆分为单词(最典型用法)
sentences = sc.parallelize(["I love python", "python is great"])
words = sentences.flatMap(lambda s: s.split())  # 结果: ["I", "love", "python", "python", "is", "great"]

# 示例2:展开嵌套列表
data = sc.parallelize([[1, 2], [3, 4, 5], [6]])
flattened = data.flatMap(lambda x: x)  # 结果: [1, 2, 3, 4, 5, 6]

3、reduceByKey () 方法:按 Key 聚合计算

1.核心原理

reduceByKey() 是 Pair RDD(键值对 RDD) 的专用算子,它的工作流程是:

  1. 按照 Key 对 RDD 中的元素进行分组(相同 Key 的元素分为一组
  2. 对每个组内的 Value 应用聚合函数(通常是求和、求积、求最大值等)
  3. 每个组最终生成一个 (Key, 聚合结果) 的元素

2.关键特点

  • 仅适用于 Pair RDD:输入必须是 (Key, Value) 形式的二元元组
  • 分组聚合:先分组后聚合,聚合逻辑由用户定义
  • 优化特性:会在 Map 阶段进行局部聚合(减少网络传输数据量)

在单词计数中:

result_rdd = word_with_one_rdd.reduceByKey(lambda a, b: a + b)

word_with_one_rdd 中的元素是:[("spark", 1), ("hadoop", 1), ("spark", 1)]
处理过程:

  1. 分组:按 Key 分组得到两组
    • "spark" 组:[(1), (1)]
    • "hadoop" 组:[(1)]
  2. 聚合:对每组应用求和函数
    • "spark" 组:1 + 1 = 2
    • "hadoop" 组:1(只有一个元素,直接保留)
      最终 result_rdd 的元素为:[("spark", 2), ("hadoop", 1)]

3.聚合函数详解

reduceByKey() 的参数是一个二元函数(接收两个参数,返回一个结果),这个函数需要满足:

  • 交换律:a + b = b + a
  • 结合律:(a + b) + c = a + (b + c)

常见的聚合逻辑:

# 求和(单词计数用的就是这个)
rdd.reduceByKey(lambda a, b: a + b)

# 求积
rdd.reduceByKey(lambda a, b: a * b)

# 求最大值
rdd.reduceByKey(lambda a, b: a if a > b else b)

4.更多示例

# 示例:统计每个用户的消费总额
transactions = sc.parallelize([
    ("Alice", 100), ("Bob", 50), ("Alice", 200), ("Bob", 150)
])
total_spent = transactions.reduceByKey(lambda a, b: a + b)
# 结果: [("Alice", 300), ("Bob", 200)]

五、总结

1.三者综合对比与协作关系

算子输入类型输出类型核心作用典型应用场景
map()任意类型任意类型一对一转换数据格式转换、值计算
flatMap()任意类型任意类型拆分并扁平化文本分词、列表展开
reduceByKey()键值对 (K,V)键值对 (K,V')按 Key 聚合分组统计、求和 / 最大值计算

这三个算子共同完成了从原始文本到单词计数结果的转换,体现了 Spark 的核心思想:将复杂计算分解为一系列简单的转换操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值