目录
[1. Spark是什么](#1. Spark是什么)
[2. PySpark是什么](#2. PySpark是什么)
[3. 为什么要学习PySpark](#3. 为什么要学习PySpark)
[1. 安装PySpark](#1. 安装PySpark)
[2. 构建SparkContext入口对象](#2. 构建SparkContext入口对象)
[3. PySpark编程模型](#3. PySpark编程模型)
[1. RDD对象](#1. RDD对象)
[2. Python数据容器转RDD(parallelize)](#2. Python数据容器转RDD(parallelize))
[3. 读取文件转RDD(textFile)](#3. 读取文件转RDD(textFile))
[1. map算子(逐个处理)](#1. map算子(逐个处理))
[2. flatMap算子(逐个处理 + 解除嵌套)](#2. flatMap算子(逐个处理 + 解除嵌套))
[3. reduceByKey算子(按Key聚合)](#3. reduceByKey算子(按Key聚合))
[4. filter算子(过滤)](#4. filter算子(过滤))
[5. distinct算子(去重)](#5. distinct算子(去重))
[6. sortBy算子(排序)](#6. sortBy算子(排序))
[1. 输出为Python对象](#1. 输出为Python对象)
[2. 输出到文件](#2. 输出到文件)
一、前言介绍
1. Spark是什么
Spark :Apache Spark是用于大规模数据 处理的统一分析引擎,用于调度成百上千的服务器集群,计算TB、PB乃至EB级别的海量数据。
2. PySpark是什么
PySpark:Spark官方开发的Python语言第三方库,Python开发者可以使用pip安装并使用。
3. 为什么要学习PySpark
-
大数据开发是Python的高薪就业方向
-
Spark(PySpark)是大数据开发的核心技术栈
二、基础准备
1. 安装PySpark
pip install pyspark
# 使用清华镜像源(更快)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark
2. 构建SparkContext入口对象
from pyspark import SparkConf, SparkContext
# 创建Spark配置
conf = SparkConf().setMaster("local[*]").setAppName("MyApp")
# 创建SparkContext入口对象
sc = SparkContext(conf=conf)
print("PySpark环境已启动")
3. PySpark编程模型
数据输入 → 数据处理计算 → 数据输出
↓ ↓ ↓
RDD对象 RDD成员方法 Python对象/文件
三、数据输入
1. RDD对象
RDD(弹性分布式数据集):PySpark中数据计算的载体,提供数据存储和计算方法。
2. Python数据容器转RDD(parallelize)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("CreateRDD")
sc = SparkContext(conf=conf)
# list转RDD
rdd1 = sc.parallelize([1, 2, 3, 4, 5])
print(rdd1.collect()) # [1, 2, 3, 4, 5]
# tuple转RDD
rdd2 = sc.parallelize((1, 2, 3, 4, 5))
print(rdd2.collect()) # [1, 2, 3, 4, 5]
# set转RDD
rdd3 = sc.parallelize({1, 2, 3, 4, 5})
print(rdd3.collect()) # [1, 2, 3, 4, 5]
# dict转RDD(只有key被保留)
rdd4 = sc.parallelize({"a": 1, "b": 2, "c": 3})
print(rdd4.collect()) # ['a', 'b', 'c']
# str转RDD(每个字符为一个元素)
rdd5 = sc.parallelize("hello")
print(rdd5.collect()) # ['h', 'e', 'l', 'l', 'o']
sc.stop()
3. 读取文件转RDD(textFile)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("ReadFile")
sc = SparkContext(conf=conf)
# 读取文本文件
rdd = sc.textFile("data.txt")
print(rdd.collect())
sc.stop()
四、数据计算(核心算子)
1. map算子(逐个处理)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("MapDemo")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 3, 4, 5])
# 每个元素乘以2
rdd2 = rdd.map(lambda x: x * 2)
print(rdd2.collect()) # [2, 4, 6, 8, 10]
# 每个元素转为字符串
rdd3 = rdd.map(lambda x: f"数字: {x}")
print(rdd3.collect()) # ['数字: 1', '数字: 2', '数字: 3', '数字: 4', '数字: 5']
# 链式调用
result = sc.parallelize([1, 2, 3, 4, 5]) \
.map(lambda x: x * 2) \
.map(lambda x: x + 1) \
.collect()
print(result) # [3, 5, 7, 9, 11]
sc.stop()
2. flatMap算子(逐个处理 + 解除嵌套)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("FlatMapDemo")
sc = SparkContext(conf=conf)
# map:嵌套结构保留
rdd1 = sc.parallelize(["hello world", "python spark"])
result1 = rdd1.map(lambda x: x.split(" ")).collect()
print(result1) # [['hello', 'world'], ['python', 'spark']]
# flatMap:解除嵌套
rdd2 = sc.parallelize(["hello world", "python spark"])
result2 = rdd2.flatMap(lambda x: x.split(" ")).collect()
print(result2) # ['hello', 'world', 'python', 'spark']
# flatMap常用于单词拆分
words = sc.parallelize(["apple banana", "cat dog", "hello world"]) \
.flatMap(lambda x: x.split(" ")) \
.collect()
print(words) # ['apple', 'banana', 'cat', 'dog', 'hello', 'world']
sc.stop()
3. reduceByKey算子(按Key聚合)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("ReduceByKeyDemo")
sc = SparkContext(conf=conf)
# 按key聚合:相同的key进行两两计算
data = [("苹果", 10), ("香蕉", 5), ("苹果", 8), ("香蕉", 3), ("苹果", 2)]
rdd = sc.parallelize(data)
# 按key求和
result = rdd.reduceByKey(lambda a, b: a + b).collect()
print(result) # [('苹果', 20), ('香蕉', 8)]
# 按key求最大值
max_result = rdd.reduceByKey(lambda a, b: max(a, b)).collect()
print(max_result) # [('苹果', 10), ('香蕉', 5)]
sc.stop()
4. filter算子(过滤)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("FilterDemo")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 过滤偶数
evens = rdd.filter(lambda x: x % 2 == 0).collect()
print(evens) # [2, 4, 6, 8, 10]
# 过滤大于5的数
greater = rdd.filter(lambda x: x > 5).collect()
print(greater) # [6, 7, 8, 9, 10]
sc.stop()
5. distinct算子(去重)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("DistinctDemo")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
unique = rdd.distinct().collect()
print(sorted(unique)) # [1, 2, 3, 4]
sc.stop()
6. sortBy算子(排序)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("SortByDemo")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([("苹果", 10), ("香蕉", 5), ("橙子", 8), ("葡萄", 3)])
# 按值排序(升序)
sorted_asc = rdd.sortBy(lambda x: x[1], ascending=True).collect()
print(sorted_asc) # [('葡萄', 3), ('香蕉', 5), ('橙子', 8), ('苹果', 10)]
# 按值排序(降序)
sorted_desc = rdd.sortBy(lambda x: x[1], ascending=False).collect()
print(sorted_desc) # [('苹果', 10), ('橙子', 8), ('香蕉', 5), ('葡萄', 3)]
# 全局排序需要设置分区数为1
sorted_global = rdd.sortBy(lambda x: x[1], ascending=False, numPartitions=1).collect()
print(sorted_global)
sc.stop()
五、数据输出
1. 输出为Python对象
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("OutputDemo")
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 3, 4, 5])
# collect():转换为list
result_list = rdd.collect()
print(result_list) # [1, 2, 3, 4, 5]
# count():统计元素个数
count = rdd.count()
print(count) # 5
# take(n):取出前n个元素
first_three = rdd.take(3)
print(first_three) # [1, 2, 3]
# reduce():自定义聚合
total = rdd.reduce(lambda a, b: a + b)
print(total) # 15
sc.stop()
2. 输出到文件
import os
from pyspark import SparkConf, SparkContext
# 配置Hadoop依赖(Windows需要)
os.environ['HADOOP_HOME'] = 'D:/hadoop-3.0.0'
conf = SparkConf().setMaster("local[*]").setAppName("SaveFile")
# 设置分区数为1,避免输出多个文件
conf.set("spark.default.parallelism", "1")
sc = SparkContext(conf=conf)
rdd = sc.parallelize(["hello world", "pyspark is great", "data processing"])
# 保存为文本文件
rdd.saveAsTextFile("output")
sc.stop()
六、综合案例
案例1:WordCount(单词计数)
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("WordCount")
sc = SparkContext(conf=conf)
# 读取文件
rdd = sc.textFile("words.txt")
# 处理流程
result = rdd \
.flatMap(lambda line: line.split(" ")) \ # 拆分单词
.map(lambda word: (word, 1)) \ # 转换为(word, 1)
.reduceByKey(lambda a, b: a + b) \ # 按单词聚合
.sortBy(lambda x: x[1], ascending=False) \ # 按次数降序
.collect()
# 输出结果
for word, count in result:
print(f"{word}: {count}")
sc.stop()
假设words.txt内容:
hello world hello python
spark hello python
pyspark spark hello
输出:
hello: 4
python: 2
spark: 2
world: 1
pyspark: 1
案例2:销售数据分析
import json
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("SalesAnalysis")
sc = SparkContext(conf=conf)
# 模拟订单数据(JSON格式)
orders_data = [
'{"id":1,"category":"平板电脑","areaName":"北京","money":1450}',
'{"id":2,"category":"手机","areaName":"北京","money":8412}',
'{"id":3,"category":"电脑","areaName":"上海","money":1513}',
'{"id":4,"category":"家电","areaName":"北京","money":1550}',
'{"id":5,"category":"电脑","areaName":"杭州","money":1550}',
'{"id":6,"category":"家具","areaName":"北京","money":6661}',
'{"id":7,"category":"书籍","areaName":"北京","money":5550}',
'{"id":8,"category":"食品","areaName":"北京","money":5520}',
'{"id":9,"category":"服饰","areaName":"杭州","money":9000}'
]
# 创建RDD
rdd = sc.parallelize(orders_data)
# 解析JSON
def parse_json(line):
data = json.loads(line)
return (data["areaName"], data["money"], data["category"])
parsed = rdd.map(parse_json)
# 1. 各个城市销售额排名(从大到小)
city_sales = parsed \
.map(lambda x: (x[0], x[1])) \
.reduceByKey(lambda a, b: a + b) \
.sortBy(lambda x: x[1], ascending=False) \
.collect()
print("=== 各城市销售额排名 ===")
for city, money in city_sales:
print(f"{city}: {money}元")
# 2. 全部城市有哪些商品类别在售卖
all_categories = parsed \
.map(lambda x: x[2]) \
.distinct() \
.collect()
print("\n=== 全部商品类别 ===")
print(all_categories)
# 3. 北京市有哪些商品类别在售卖
beijing_categories = parsed \
.filter(lambda x: x[0] == "北京") \
.map(lambda x: x[2]) \
.distinct() \
.collect()
print("\n=== 北京市商品类别 ===")
print(beijing_categories)
sc.stop()
输出:
=== 各城市销售额排名 ===
北京: 23188元
杭州: 10550元
上海: 1513元
=== 全部商品类别 ===
['平板电脑', '手机', '电脑', '家电', '家具', '书籍', '食品', '服饰']
=== 北京市商品类别 ===
['平板电脑', '手机', '家电', '家具', '书籍', '食品']
案例3:搜索引擎日志分析
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local[*]").setAppName("LogAnalysis")
sc = SparkContext(conf=conf)
# 模拟日志数据格式:时间|关键词
log_data = [
"2024-01-01 10:00:00|Python教程",
"2024-01-01 10:05:00|Spark入门",
"2024-01-01 10:10:00|黑马程序员",
"2024-01-01 10:10:00|Python教程",
"2024-01-01 11:00:00|大数据开发",
"2024-01-01 11:05:00|黑马程序员",
"2024-01-01 11:10:00|Spark入门",
"2024-01-01 12:00:00|黑马程序员",
"2024-01-01 12:00:00|Python教程"
]
rdd = sc.parallelize(log_data)
# 解析日志
def parse_log(line):
time, keyword = line.split("|")
hour = time.split(" ")[1].split(":")[0] # 提取小时
return (hour, keyword)
parsed = rdd.map(parse_log)
# 1. 热门搜索时间段(按搜索次数排名)
hour_count = parsed \
.map(lambda x: (x[0], 1)) \
.reduceByKey(lambda a, b: a + b) \
.sortBy(lambda x: x[1], ascending=False) \
.take(3)
print("=== 热门搜索时间段 Top3 ===")
for hour, count in hour_count:
print(f"{hour}点: {count}次")
# 2. 热门搜索词 Top3
keyword_count = parsed \
.map(lambda x: (x[1], 1)) \
.reduceByKey(lambda a, b: a + b) \
.sortBy(lambda x: x[1], ascending=False) \
.take(3)
print("\n=== 热门搜索词 Top3 ===")
for keyword, count in keyword_count:
print(f"{keyword}: {count}次")
# 3. 统计"黑马程序员"在哪个时段被搜索最多
heimakeyword = parsed \
.filter(lambda x: x[1] == "黑马程序员") \
.map(lambda x: (x[0], 1)) \
.reduceByKey(lambda a, b: a + b) \
.sortBy(lambda x: x[1], ascending=False) \
.first()
print(f"\n=== 黑马程序员搜索最多时段 ===")
print(f"{heimakeyword[0]}点: {heimakeyword[1]}次")
sc.stop()
输出:
=== 热门搜索时间段 Top3 ===
10点: 4次
11点: 3次
12点: 2次
=== 热门搜索词 Top3 ===
Python教程: 3次
黑马程序员: 3次
Spark入门: 2次
=== 黑马程序员搜索最多时段 ===
10点: 1次
11点: 1次
12点: 1次
Hadoop运行
提交命令:
bin/spark-submit --master yarn --num-executors 3 --queue root.teach --executor-cores 4 --executor-memory 4g /home/hadoop/demo.py

七、PySpark速查表
安装与环境
| 操作 | 命令 |
|---|---|
| 安装PySpark | pip install pyspark |
| 创建入口 | sc = SparkContext(conf=conf) |
数据输入
| 方法 | 说明 |
|---|---|
sc.parallelize(data) |
Python容器 → RDD |
sc.textFile(path) |
文本文件 → RDD |
数据计算(算子)
| 算子 | 说明 | 示例 |
|---|---|---|
map(func) |
逐个元素处理 | rdd.map(lambda x: x*2) |
flatMap(func) |
处理并解除嵌套 | rdd.flatMap(lambda x: x.split()) |
filter(func) |
过滤(True保留) | rdd.filter(lambda x: x>5) |
reduceByKey(func) |
按Key聚合 | rdd.reduceByKey(lambda a,b: a+b) |
distinct() |
去重 | rdd.distinct() |
sortBy(func, ascending) |
排序 | rdd.sortBy(lambda x: x[1]) |
数据输出
| 方法 | 说明 |
|---|---|
collect() |
RDD → list |
count() |
统计元素个数 |
take(n) |
取前n个元素 |
first() |
取第一个元素 |
reduce(func) |
聚合计算 |
saveAsTextFile(path) |
保存到文件 |
代码跨行编写(使用\)
# 使用反斜杠实现跨行编写
result = sc.textFile("data.txt") \
.flatMap(lambda x: x.split(" ")) \
.map(lambda x: (x, 1)) \
.reduceByKey(lambda a, b: a + b) \
.collect()