分布式的计算框架之Spark(python第三方库视角学习PySpark)

news2024/9/22 9:59:27

基本介绍

Apache Spark是专为大规模数据处理而设计的快速通用的计算引擎 。现在形成一个高速发展应用广泛的生态系统。

特点介绍

Spark 主要有三个特点:

首先,高级 API 剥离了对集群本身的关注,Spark 应用开发者可以专注于应用所要做的计算本身。

其次,Spark 很快,支持交互式计算和复杂算法。

最后,Spark 是一个通用引擎,可用它来完成各种各样的运算,包括 SQL 查询、文本处理、机器学习等,而在 Spark 出现之前,我们一般需要学习各种各样的引擎来分别处理这些需求。(来源百度百科)

park对python语言的支持--->PySpark

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

PySpark是由Spark官方开发的Python语言第三方库Python开发者可以使用pip程序快速的安装PySpark并像其它三方库那样直接使用。

基础准备

PySpark库的安装

在命令行中输入:pip install pyspark

使用国内代理镜像网站:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark

PySpark执行环境入口对象的构建

想要使用PySpark库完成数据处理,首先需要构建一个执行环境入口对象。

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

如何通过代码获得类对象,代码如下:

from pyspark import SparkConf, SparkContext

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)
# 打印pyspark的运行版本
print(sc.version)
# 停止SparkContext对象的运行(停止pyspark程序)
sc.stop()

image.png

PySpark的编程模型

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

image.png

数据输入

RDD对象

PySpark支持多种数据的输入,在输入完成后,都会得到一个:RDD类的对象

RDD全称为: 弹性分布式数据集(Resilient Distributed Datasets)

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

(1)数据存储在RDD内

(2)各类数据的计算方法,也都是RDD的成员方法

(3)RDD的数据计算方法,返回值依旧是RDD对象

Python数据容器转RDD对象

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

from pyspark import SparkConf, SparkContext

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)
rdd1 = sc.parallelize([1, 2, 3, 4, 5])  # 列表
rdd2 = sc.parallelize((1, 2, 3, 4, 5))  # 元组
rdd3 = sc.parallelize("study python")  # 字符串
rdd4 = sc.parallelize({1, 2, 3, 4, 5})  # 集合
rdd5 = sc.parallelize({"key1": "value1", "key2": "value2", "key3": "value3"})  # 字典

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

# # 停止SparkContext对象的运行(停止pyspark程序)
sc.stop()

image.png

注意:

(1)字符串会被拆分出1个个的字符,存入RDD对象字典

(2)仅有key会被存入RDD对象

读取文件转RDD对象

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

前面逻辑都是一样的,只是调用方法不一样,需要使用sc.textFile

from pyspark import SparkConf, SparkContext

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象

# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)

rdd = sc.textFile("G:\资料\2011年1月销售数据.txt")

# 如果要查看RDD里面有什么内容,需要用collect()方法
print(rdd.collect())

# # 停止SparkContext对象的运行(停止pyspark程序)
sc.stop()

image.png

数据计算

PySpark的数据计算,都是依赖RDD对象内置丰富的“成员方法(算子)”来进行的

因为spark是一个分布式程序,内部运行机制比较复杂,暂不讨论,我们只需要知道在python中运行spark程序时,需要额外增加以下代码,否则会报错:spark找不到python程序

# 添加'PYSPARK_PYTHON'和'PYSPARK_DRIVER_PYTHON'的执行环境
os.environ['PYSPARK_PYTHON'] = sys.executable  # "E:/python/python.exe"
os.environ['PYSPARK_DRIVER_PYTHON'] = sys.executable  # "E:/python/python.exe"

(1)map方法

功能:将RDD的数据一条条处理,返回新的RDD

语法:rdd.map(fun) # 需要传入一个函数

需求:给[1,2,3,4,5]每个数字乘以10

代码如下:

import sys
from pyspark import SparkConf, SparkContext
import os

# 添加'PYSPARK_PYTHON'和'PYSPARK_DRIVER_PYTHON'的执行环境
os.environ['PYSPARK_PYTHON'] = sys.executable  # "E:/python/python.exe"
os.environ['PYSPARK_DRIVER_PYTHON'] = sys.executable  # "E:/python/python.exe"

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)
# 需求:通过map方法将全部数据都乘以10
rdd = sc.parallelize([1, 2, 3, 4, 5])
# 把rdd中的每一个数据都调用匿名函数(也可通过def重新定义函数)去处理
rdd2 = rdd.map(lambda x: x * 10)
print(rdd2.collect())
# 停止SparkContext对象的运行(停止pyspark程序)
sc.stop()

image.png

(2)flatMap方法

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

# 嵌套的list
list = [[1,2,3],[4,5,6],[7,8,9]]

# 解除了嵌套
list = [1,2,3,4,5,6,7,8,9]

示例代码:

import sys
from pyspark import SparkConf, SparkContext
import os

# 添加'PYSPARK_PYTHON'和'PYSPARK_DRIVER_PYTHON'的执行环境
os.environ['PYSPARK_PYTHON'] = sys.executable  # "E:/python/python.exe"
os.environ['PYSPARK_DRIVER_PYTHON'] = sys.executable  # "E:/python/python.exe"

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)

rdd = sc.parallelize(["hello python", "hello word", "hello friend"])
# 需求:将RDD中的每一个单词都提取出来
rdd2 = rdd.flatMap(lambda x: x.split(" "))
print(rdd2.collect())

image.png

(3)reduceByKey方法

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

语法:

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

示例代码:

# 前面创建RDD对象不做赘述了
# 准备一个RDD
rdd = sc.parallelize([('男', 99), ('男', 80), ('男', 70), ('女', 100), ('女', 85)])
# 求男生和女生两个组的成绩之和
rdd2 = rdd.reduceByKey(lambda a, b: a + b)
print(rdd2.collect())

image.png

案例1

对下面txt文件中的单词进行计数统计

image.png

代码如下:

import sys
from pyspark import SparkConf, SparkContext
import os

# 添加'PYSPARK_PYTHON'和'PYSPARK_DRIVER_PYTHON'的执行环境
os.environ['PYSPARK_PYTHON'] = sys.executable  # "E:/python/python.exe"
os.environ['PYSPARK_DRIVER_PYTHON'] = sys.executable  # "E:/python/python.exe"

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)

# 读取数据文件
rdd = sc.textFile("G:/hello.txt")
# 读取全部单词
word_rdd = rdd.flatMap(lambda x: x.split(" "))
# 将所有单词都转换成二元元组,单词为key,value设置为1
word_one_rdd = word_rdd.map(lambda word: (word, 1))
# 分组并求和传承传承
result_rdd = word_one_rdd.reduceByKey(lambda a, b: a + b)
print(result_rdd.collect())

image.png

(4)filter方法

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

语法:

rdd.filter(func)
# func: (T)-->bool  传入1个参数进来随意类型,返回值必须是true or false

示例代码:

# 前面创建RDD对象不做赘述了
# 准备一个RDD
rdd = sc.parallelize([1, 2, 3, 4, 5])
# 对RDD的数据进行过滤,偶数返回true,保留偶数
rdd2 = rdd.filter(lambda num: num % 2 == 0)
print(rdd2.collect())

image.png

(5)distinct方法

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

语法:rdd.distinct()

实例代码:

# 前面创建RDD对象不做赘述了
# 准备一个RDD
rdd = sc.parallelize([1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9])
# 对RDD的数据进行去重
rdd2 = rdd.distinct()
print(rdd2.collect())

image.png

(6)stortBy方法

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

语法:

rdd.sortBy(func,ascending=False, numPartitions=1)
# func: (T) -> U: 告知按照rdd中的哪个数据进行排序,比如 lambda x: [1] 表按照rdd中的第二列元素进行排序
# ascending True升序 False 降序
# numPartitions: 用多少分区排序

示例代码:

以上对单词进行计数统计的案例1中,对结果按照单词出现的次数从大到小进行排序

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

image.png

案例2

需求:对以下文件使用spark读取文件进行计算:

(1)各个城市销售额排名,从大到小

(2)全部城市,有哪些商品类别在售卖

(3)北京市有哪些商品类别在售卖

image.png

案例代码:

import sys
from pyspark import SparkConf, SparkContext
import os
import json

# 添加'PYSPARK_PYTHON'和'PYSPARK_DRIVER_PYTHON'的执行环境
os.environ['PYSPARK_PYTHON'] = sys.executable  # "E:/python/python.exe"
os.environ['PYSPARK_DRIVER_PYTHON'] = sys.executable  # "E:/python/python.exe"

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")  # 链式调用,不管调用什么样的方法,返回的都是同一个对象
# 基于SparkConf类对象创建SparkContext对象
sc = SparkContext(conf=conf)

# (1)城市销售额排名
# 读取数据文件
file_rdd = sc.textFile("G:/orders.txt")
# 读取文件中单个json字符串
json_str_rdd = file_rdd.flatMap(lambda x: x.split("|"))
# 将单个字符串转换为字典
dict_rdd = json_str_rdd.map(lambda x: json.loads(x))
# 取出城市和销售额数据(城市,销售额)
city_money_rdd = dict_rdd.map(lambda x: (x['areaName'], int(x['money'])))
# 按照城市分组,按照销售额累计
city_result_rdd = city_money_rdd.reduceByKey(lambda a, b: a + b)
# 按照销售额累计结果进行排序
result1_rdd = city_result_rdd.sortBy(lambda x: x[1], ascending=False, numPartitions=1)
print("各个城市销售额排名,从大到小:", result1_rdd.collect())
# (2)全部城市,有哪些商品类别在售卖
category_rdd = dict_rdd.map(lambda x: x['category']).distinct()
print("全部城市,有哪些商品类别在售卖:", category_rdd.collect())
# (3)北京市有哪些商品类别在售卖
beijing_data_rdd = dict_rdd.filter(lambda x: x['areaName'] == '北京')
beijing_category = beijing_data_rdd.map(lambda x: x['category']).distinct()
print('北京市有哪些商品类别在售卖:', beijing_category.collect())

image.png

数据输出

RDD的结果输出为Python对象的各类方法

(1)collect方法

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

语法:rdd.collect(),返回值是一个list

此方法我们前面一直在使用,不做赘述

(2)reduce方法

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

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

示例代码:

rdd = sc.parallelize([1, 2, 3, 4, 5])
print(rdd.reduce(lambda a, b: a + b))
# 输出结果为两两相加的值:15

(3)take方法

功能:取RDD的前n个元素,组成list返回

语法:rdd.take(num),num代表前几个元素

示例代码:

rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(rdd.take(5))
# 输出结果为:[1, 2, 3, 4, 5]

(4)count方法

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

用法:rdd.count()

示例代码:

rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(rdd.count())
# 输出结果为:10

注意:

关于Spark的方法(算子)还有很多很多,我们目前不是深入学习python语言,同时也没有学习分布式,只是简单学习对自动化测试打下基础,所以本篇文章只介绍了最基础的几个。

将RDD的内容输出到文件中

(5)saveAsTextFile方法

功能:将RDD的数据写入文本文件中,支持本地写出,hdfs(Hadoop分布式文件系统)等文件系统。

语法: rdd.saveAsTextFile("../data/output/test.txt")

想要这个方法正常运行,还需要配置Hadoop依赖,自行百度配置

运行之后,内容会存在多个分区中,输出的结果是一个文件夹,有几个分区就输出多少个结果文件

修改RDD分区为1个

方式1:SparkConf对象设置conf.set("spark.default.parallelism", "1")

方式2:创建RDD的时候,sc.parallelize方法传入numSlices参数为1

# 方式1,SparkConf对象设置属性全局并行度为1:
conf = SparkConf().setMaster("Tocal[*]").setAppName("test_spark")
conf.set("spark.default.parallelism", "1")
sc = SparkContext(conf=conf)
# 方式2, 创建RDD的时候设置(parallelize方法传入numSlices参数为1)
rdd1 = sc.parallelize([1, 2, 3, 4, 5], numSlices=1)
rdd1 = sc.parallelize([1, 2, 3, 4, 5], 1)

行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1596805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言面试题之奇偶链表

奇偶链表 实例要求 1、给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表;2、第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推&#x…

快速掌握Spring监控(Spring Boot admin)

监控 监控可视化监控平台Admin底层逻辑info 自定义端点 监控 监控的作用: 监控服务状态是否宕机监控服务运行指标(内存,虚拟机,线程,请求等)监控日志管理服务(服务下线) 监控的实…

详解IP证书申请

申请IP证书,也被称为IP SSL证书,是一种特殊的SSL证书,它不同于传统的域名验证(DV)证书,是通过验证公网IP地址而不是域名来确保安全连接。这种证书用于保护IP地址,并在安装后起到加密作用。以下是…

李廉洋:4.16黄金,原油最新资讯,亚盘面走势分析及策略。

周一,10年期美国国债收益率攀升3个基点,至4.55%,原因是投资者在权衡中东紧张局势加剧演变为全面地区战争的风险。美国国债将成为市场关注的焦点,上周美国国债收益率上升12个基点,至去年11月以来的最高水平,…

TC387实现SPI自通讯

TC387实现SPI自通讯 预期效果: TC387上定义两个SPI通讯接口,一个用于发数据一个用于收数据。准确无误的收到一次数据就对核心板led灯的状态进行一次翻转。 由于实验设备有限,只能想办法通过现有设备进行实验。 实现过程: 最开…

【学习笔记PPT摘录】lan.289.24.4-15

1.纪念品分组.双指针-01 #include <bits/stdc++.h> using namespace std;int A[40000];// 纪念品价值均衡// 把购来的纪念品进行分组 之和不超过整数 w// 每组只能有两个纪念品 希望分组的数目要少// 贪心的策略就是 每个较大的数找到一个 最大的较小的数使其能够小于w//…

基于注解以及配置类使用SpringIoc

四 基于注解方式使用SpringIoc 和 XML 配置文件一样&#xff0c;注解本身并不能执行&#xff0c;注解本身仅仅只是做一个标记&#xff0c;具体的功能是框架检测到注解标记的位置&#xff0c;然后针对这个位置按照注解标记的功能来执行具体操作。 本质上&#xff1a;所有一切的…

京东商品详情API接口(商品属性丨sku价格丨详情图丨标题等数据)

京东商品详情API接口是京东开放平台提供的一种API接口&#xff0c;通过调用该接口&#xff0c;开发者可以获取京东商品的标题、价格、库存、月销量、总销量、详情描述、图片等详细信息。下面针对您提到的商品属性、SKU价格、详情图以及标题等数据&#xff0c;做具体介绍&#x…

c++ 多文件编程

1.结构目录 声明类:用于声明方法,方便方法管理和调用&#xff1b; 实现类:用于实现声明的方法; 应用层:调用方法使用 写过java代码的兄弟们可以这么理解&#xff1a; 声明类 为service层 实现类 为serviceimpl层 应用层 为conlloter层 2.Dome 把函数声明放在头文件xxx.h中&…

STM32学习和实践笔记(5):时钟树

STM32一共有4个时钟源。外部时钟高低速各一个&#xff0c;内部时钟高低速各一个。 外部高速时钟是&#xff1a;4-16MHZ的HSE OSC。HS表示高速high speed. E表示外部的external。开发板该处安装的8M晶振。 外部低速时钟是&#xff1a;32.768KHz的LSI OSC。LS表示高速low speed…

1.JAVASE练习题(递归篇)

1.递归求解汉诺塔问题 public static void move(char pos1,char pos2) {System.out.print(pos1"->"pos2" "); }public static void hanoi(int n,char pos1,char pos2,char pos3) {if(n 1) {move(pos1,pos3);return;}hanoi(n-1,pos1,pos3,pos2);move(p…

六、数据呈现

目录 6.1 理解输入输出 6.1.1 标准文件描述符 1 STDIN &#xff08;0&#xff09; 2 STDOUT &#xff08;1&#xff09; 3 STDERR&#xff08;2&#xff09; 6.1.2 重定向错误 1 只重定向错误 2 重定向错误和数据 6.2 在脚本中重定向输出 6.2.1 临时重定向 6.2.2 永…

项目——boost搜索引擎

今天我们来写一个boost搜索引擎&#xff01; &#xff08;后续如果有更新&#xff0c;这个博客也会更新&#xff09; gitee连接:boost搜索引擎: boost搜索引擎 首先我们要介绍一下我们这个项目&#xff0c;我们项目的目的是通过我们的搜索引擎能够通过关键字查找到对应的网页…

中国工控网zggk.item_get API:电商行业数据获取的革新力量

随着信息技术的快速发展&#xff0c;电商行业已经深入渗透到各个领域&#xff0c;成为推动经济发展的重要力量。在这个过程中&#xff0c;数据获取成为了电商企业不可或缺的一环。中国工控网推出的zggk.item_get API&#xff0c;以其高效、准确的数据获取能力&#xff0c;成为了…

MySQL 快问快答

我写这篇文章的目的只有一个&#xff1a;通过这些问题来帮助我去将我脑子里的MySQL脑图给巩固熟悉&#xff0c;通过回答这些问题&#xff0c;让我对脑子里的MySQL知识有更深的印象&#xff0c;当什么时候我的MySQL脑图不熟的时候&#xff0c;我就可以拿这篇文章来去巩固一下&am…

六、新闻主题分类任务

以一段新闻报道中的文本描述内容为输入&#xff0c;使用模型帮助我们判断它最有可能属于哪一种类型的新闻&#xff0c;这是典型的文本分类问题。我们这里假定每种类型是互斥的&#xff0c;即文本描述有且只有一种类型&#xff0c;例如一篇新闻不能即是娱乐类又是财经类&#xf…

mybatis-puls乐观锁

一&#xff0c;乐观锁&悲观锁 乐观锁: 顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试 悲观锁;顾名思义十分悲观,他总是认为出现问题,无论干什么都会上锁!再去操作! 乐观锁实现方式: 取出记录时,获取当前version更新时,带上…

线程通信-java

线程通信 当多个线程操作共享多资源时&#xff0c;线程间通过某种方式相互告知自己的状态&#xff0c;以相互协调&#xff0c; 并避免无效的资源争夺。 线程通信的常见模型&#xff08;生产者与消费者模型&#xff09; 生产者线程负责生产数据 消费者线程负责消费生产者生…

Redis部署之主从

使用两台云服务器&#xff0c;在 Docker 下部署。 Redis版本为&#xff1a;7.2.4 下载并配置redis 配置文件 下载 wget -c http://download.redis.io/redis-stable/redis.conf配置 master节点配置 bind 0.0.0.0 # 使得Redis服务器可以跨网络访问,生产环境请考虑…

C语言 03 VSCode开发

安装好 C 语言的开发环境后&#xff0c;就需要创建项目进行开发了。 使用 IDE&#xff08;集成开发环境&#xff09;进行开发了。 C 语言的开发工具很多&#xff0c;现在主流的有 Clion、Visual Studio、VSCode。 这里以 VSCode 作为演示。 创建项目 安装 VSCode。 推荐直接在…