Python入门(3)——第三阶段:PySpark案例实战(更新中)

Python入门(1):Python入门(1):第一阶段_python最新的解释器-CSDN博客

Python入门(2):Python入门(2):第二阶段——面向对象-CSDN博客

 Python入门(3):Python入门(3)——第三阶段:PySpark案例实战(更新中)-CSDN博客


-- 第三阶段 --

一、 基础准备

1.什么是PySpark

Spark定义:Apache Spark是用于大规模数据处理的统一分析引擎

Spark对Python语言的支持,重点体现在,Python第三方库:PySpark之上。

PySpark是由Spark官方开发的Python语言第三方库。

2.pyspark库的安装

在“CDM”命令提示符内输入:pip install pyspark

或者使用国内代理镜像网站(清华大学源):pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark

3.构建PySpark执行环境入口对象 

PySpark执行环境入口对象是:类SparkContext的类对象

from pyspark import SparkConf,SparkContext
#创建SparkConf对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")
#基于SparkConf类对象创建SparkContext对象  (sc是后续重要对象)
sc = SparkContext(conf=conf)
#打印PySpark的运行版本
print(sc.version)
#停止SparkContext对象的运行(停止PySpark程序)
sc.stop()

打印PySpark的运行版本结果:

4.Pyspark的编程模型

SparkContext类对象,是PySpark编程中一切功能的入口。

PySpark的编程,主要分为如下三大步骤:

  • 数据输入
    • 通过SparkContext类对象的成员方法,完成数据的读取操作,读取后得到RDD类对象
  • 数据处理计算
    • 通过RDD类对象的成员方法,完成各种数据计算的需求
  • 数据输出
    • 将处理完成后的RDD对象,调用各种成员方法,完成写出文件、转换为list等操作

二、数据输入

1.RDD对象

PySpark支持多种数据的输入,在输入完成后,都会得到一个:RDD类的对象
RDD全称为:弹性分布式数据集(Resilient Distributed Datasets)

PySpark针对数据的处理,都是以RDD对象作为载体,,即:

  • 数据存储在RDD内
  • 各类数据的计算方法,也都是RDD的成员方法
  • RDD的数据计算方法,返回值依旧是RDD对象

2.Python数据容器转RDD对象

PySpark支持通过SparkContext对象的paralielize成员方法,将:list、tuple、set、dict、str转换为PySpark的RDD对象。

from pyspark import  SparkConf,SparkContext

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

#通过parallelize方法将Python对象加载到Spark内,成为RDD对象
rdd1 = sc.parallelize([1,2,3,4,5])
rdd2 = sc.parallelize((1,2,3,4,5))
rdd3 = sc.parallelize("abcdefg")
rdd4 = sc.parallelize({1,2,3,4,5})
rdd5 = sc.parallelize({"key1":"value1","key2":"value2"})

#如果要查看RDD里面有什么内容,需要有collect()方法
print(rdd1.collect())
print(rdd2.collect())
print(rdd3.collect())
print(rdd4.collect())
print(rdd5.collect())

sc.stop()
#输出结果:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
['a', 'b', 'c', 'd', 'e', 'f', 'g']
[1, 2, 3, 4, 5]
['key1', 'key2']

3.读取文件转RDD对象

PySpark也支持通过SparkContext入口对象,来读取文件,来构建出RDD对象。

在D盘准备一个test.txt内容如下:

from pyspark import SparkConf,SparkContext

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

#用textFile方法,读取文件数据加载到Spark内,成为RDD对象
rdd = sc.textFile("D:/test.txt")          #文件存放的路径要写对,不然会报错
print(rdd.collect())

sc.stop()
#输出结果:
['hello', '666', 'spark', 'python', 'pyspark']

三、数据计算

1.map方法

功能:map算子,是将RDD的数据一条条处理(处理的逻辑 基于map算子中接收的处理函数),返回新的RDD。

链式调用:可多次调用算子

语法:

from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

#准备一个RDD
rdd = sc.parallelize([1,2,3,4,5])
# #通过map方法将全部数据都乘以10(简单函数可以使用lambda)
# def func(data):
#     return data * 10

#链式调用
rdd2 = rdd.map(lambda x : x * 10).map(lambda x : x + 5).map(lambda x : x - 2)

print(rdd2.collect())
#(T) -> U 接收一个传入参数,有一个返回值(对于参数和返回值的类型没有要求)
#(T) -> T 接收一个传入参数,有一个返回值(传入参数和返回值的类型要一致)

sc.stop()

#输出结果:
[13, 23, 33, 43, 53]

注意:Python3.12.5执行以上代码会报错,需要安装低版本的,比如Python3.10.11,再次执行则成功打印结果。

2.flatMap方法

功能:对RDD执行map操作,然后进行解除嵌套操作。

from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
#准备一个RDD
rdd = sc.parallelize(["hello world","Happy Mid-Autumn Festival","nice to meet you"])
#需求:将RDD数据里面的一个个单词提取出来
rdd2 = rdd.flatMap(lambda x : x.split(" "))
print(rdd2.collect()) 

#输出结果:
['hello', 'world', 'Happy', 'Mid-Autumn', 'Festival', 'nice', 'to', 'meet', 'you']

3.reduceByKey方法

功能:针对KV型RDD,自动按照key分组,然后根据你提供的聚合逻辑,完成组内数据(value)的聚合操作。

KV型:二元元组

#用法:
rdd.reduceByKey(func)
#func:(V,V)->V
#接受2个传入参数(类型要一致),返回一个返回值,类型与传入要求一致

注意:reduceByKey中接收的函数,只负责聚合,不理会分组

分组是自动by key来分组的。 

from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
#准备一个RDD
rdd = sc.parallelize([('男',99),('男',22),('女',66),('女',88)])
# 求男生和女生两个组的成绩之和
rdd2 = rdd.reduceByKey(lambda a,b:a+b)
print(rdd2.collect())

#输出结果:
[('男', 121), ('女', 154)]

4.练习案例:单词计数

要求:读取文件,统计文件内,单词的出现量

文件内容如下:

# 1.构建执行环境入口对象
from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
# 2.读取数据文件
rdd = sc.textFile("D:/test.txt")
# 3.取出所有单词
word_rdd = rdd.flatMap(lambda x : x.split(" "))
# 4.将所有单词都转换成二元元组,单词为Key,Value设置为1
word_with_one_rdd = word_rdd.map(lambda x : (x, 1))
# 5.分组求和
result_rdd = word_with_one_rdd.reduceByKey(lambda a, b: a + b)
print(result_rdd.collect())

#输出结果:
[('nihao', 4), ('python', 3), ('hello', 6), ('spark', 5), ('pyspark', 3)]

5.filter方法

功能:过滤想要的数据进行保留。

True的数据保留,False的丢弃

语法:

#语法:
rdd.filter(func)
#func:(T) -> bool 传入1个参数进来随意类型,返回值必须是True or False
from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
#准备一个RDD
rdd = sc.parallelize([1,2,3,4,5])
#对RDD数据进行过滤,保留偶数
rdd2 = rdd.filter(lambda num: num% 2 == 0)
print(rdd2.collect())
#输出结果:
[2, 4]

6.distinct方法

功能:对RDD数据进行去重,返回新RDD

#语法
rdd.distinct()  无需传参
from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

#准备一个RDD
rdd = sc.parallelize([1,1,1,2,2,3,4,5,5,5,5,6,8,8])
#对RDD数据进行去重
rdd2 = rdd.distinct()
print(rdd2.collect())
#输出结果:
[1, 2, 3, 4, 5, 6, 8]

7.sortBy方法

功能:对RDD数据进行排序,基于你指定的排序依据。

#语法
rdd.sortBy(func, ascending=False, numPartitions= 1)
#func: (T) -> U:告知按照RDD中的哪个数据进行排序,比如lambda x: x[1]表示按照RDD中的第二列元素进行排序
#ascending:True升序  False降序
#numPartitions:用多少分区排序
# 构建执行环境入口对象
from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

# 1.读取数据文件
rdd = sc.textFile("D:/test.txt")
# 2.取出所有单词
word_rdd = rdd.flatMap(lambda x : x.split(" "))
# 3.将所有单词都转换成二元元组,单词为Key,Value设置为1
word_with_one_rdd = word_rdd.map(lambda x : (x, 1))
# 4.分组求和
result_rdd = word_with_one_rdd.reduceByKey(lambda a, b: a + b)
#到这里是上一个案例(单词计数)的代码,结果为[('nihao', 4), ('python', 3), ('hello', 6), ('spark', 5), ('pyspark', 3)]

# 5.对结果进行降序排序
final_rdd = result_rdd.sortBy(lambda x: x[1],ascending=False,numPartitions=1)
print(final_rdd.collect())

#输出结果:
[('hello', 6), ('spark', 5), ('nihao', 4), ('python', 3), ('pyspark', 3)]

8.练习案例

需求,复制以上内容到文件中,使用Spark读取文件进行计算:

  • 各个城市销售额排名,从大到小
  • 全部城市,有哪些商品类别在售卖
  • 北京市有哪些商品类别在售卖
# 构建执行环境入口对象
from pyspark import SparkConf,SparkContext
import  os
import json
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

# 读取数据文件得到RDD
file_rdd = sc.textFile("D:/orders.txt")
# 取出一个个JSON字符串
json_str_rdd = file_rdd.flatMap(lambda x : x.split("|"))
# 将所有一个个JSON字符串单转换成字典
dict_rdd =json_str_rdd.map(lambda x: json.loads(x))

# TODO 需求1:城市销售额排名
# 1.1取出城市和销售额数据
#(城市,销售额)
city_with_money_rdd = dict_rdd.map(lambda x: (x['areaName'],int (x['money'])))
# 1.2按城市分组,按销售额聚合
city_result_rdd = city_with_money_rdd.reduceByKey(lambda a, b: a+ b)
# 1.3 按销售额聚合结果进行排序
result1_rdd = city_result_rdd.sortBy(lambda x: x[1],ascending=False,numPartitions=1)
print("需求1的结果是:",result1_rdd.collect())

# TODO 需求2:全部城市,有哪些商品类别在售卖
# 2.1 取出全部的商品类别并去重
category_rdd = dict_rdd.map(lambda x: x["category"]).distinct()
print("需求2的结果是:",category_rdd.collect())

# TODO 需求3:北京市有哪些商品类别在售卖
# 3.1 过滤北京市的数据
beijing_data_rdd = dict_rdd.filter(lambda x: x["areaName"] =="北京")
# 3.2 取出全部商品类别
result3_rdd = beijing_data_rdd.map(lambda x: x["category"]).distinct()
print("需求3的结果是:",result3_rdd.collect())

#输出结果:
需求1的结果是: [('北京', 91556), ('杭州', 28831), ('天津', 12260), ('上海', 1513), ('郑州', 1120)]
需求2的结果是: ['平板电脑', '家电', '书籍', '手机', '电脑', '家具', '食品', '服饰']
需求3的结果是: ['平板电脑', '家电', '书籍', '手机', '电脑', '家具', '食品', '服饰']

四、数据输出

1.RDD输出为Python对象

collect算子

功能:将RDD各个分区内的数据,统一收集到Driver中,形成一个List对象。

#用法
rdd.collect()
#返回值是一个list

reduce算子

功能:对RDD数据集按照你传入的逻辑进行聚合。

#语法:
rdd.reduce(func)
#func: (T, T) -> T
#2参数传入 1个返回值,返回值和参数要求类型一致

take算子

功能:取RDD的前N个元素,组合成list返回给你。

count算子

功能:计数RDD有多少条数据,返回值是一个数字

collect、reduce、take、count代码示例

#collect、reduce、take、count代码示例

from pyspark import SparkConf,SparkContext
import  os
os.environ["PYSPARK_PYTHON"] = "D:/Python/Python31011/python.exe"  #python解释器的位置

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

#准备一个RDD
rdd = sc.parallelize([1,2,3,4,5])

#collect算子,输出为List对象
rdd_list: list = rdd.collect()
print(rdd_list)
print(type(rdd_list))

#reduce算子,对RDD进行两两聚合
num = rdd.reduce(lambda a, b: a+ b)
print(num)

#take算子,取RDD的前N个元素,组成list返回
take_list = rdd.take(3)
print(take_list)

#count算子,计数RDD有多少条数据,返回值是一个数字
num_count = rdd.count()
print(f"rdd内有{num_count}个元素")

sc.stop()

#输出结果:
[1, 2, 3, 4, 5]
<class 'list'>
15
[1, 2, 3]
rdd内有5个元素

2.输出到文件中

saveAsTextFile算子

功能:将RDD的数据写入文本文件中。

支持本地写出,hdfs等文件系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值