利用这本书,你将学习以下内容:了解如何选择Spark转换实现优化的解决方案。探索强大的转换和归约,包括reduceByKey()、combineByKey()和mapPartitions()。理解数据分区以实现优化查询。使用PySpark设计模式构建和应用模型。对图数据应用motif查找算法。使用GraphFrames API分析图数据。对临床医学和基因组数据应用PySpark算法。学习如何在ML算法中使用和应用特征工程。了解并使用实用的数据设计模式。
编辑推荐
Apache Spark不仅速度快,易于使用,还提供了丰富的分析能力和多语言支持,掌握这个集群计算框架的实用知识已经成为数据工程师和数据科学家的必b备技能。利用这本实用指南,想要了解Spark的人能从中学习实用的PySpark算法和示例。
每一章中,本书作者会向你展示如何用一组Spark转换和算法解决一个数据问题。你会了解如何应对涉及ETL、设计模式、机器学习算法、数据分区和基因组分析的问题。每个技巧都提供了利用PySpark驱动器和shell脚本使用的PySpark算法。
专家推荐
如果你希望采用一种可伸缩的方式实现现有算法,或者正在使用Spark开发新的自定义算法,对于这些人,这本书是一个绝好的资源。
Matei Zaharia
斯坦福大学计算机科学副教授;
Databricks首席技术专家;
Apache Spark创始人
前言Spark 已经成为大规模数据分析领域事实上的标准。自从几年前Spark 诞生以来,我就一直在使用和教授Spark,在抽取、转换、加载(ETL)过程、分布式算法开发以及大规模数据分析方面,Spark 都取得了长足的进步。我最初是用Java 使用Spark,但我发现,虽然代码相当稳定,但写的代码行很长,这会让代码很难阅读。在这本书中,我决定使用PySpark(Spark 的Python API),因为用Python 展现Spark 的强大功能更为容易:代码简短,易于阅读,而且易于维护。PySpark 很强大,同时使用很简单,利用PySpark 可以用一组简单的转换和动作实现任何ETL 或分布式算法。为什么写这本书这是一本关于使用PySpark 实现数据分析的入门书。这本书提供了一组原则和示例,旨在帮助软件和数据工程师用尽可能简单的方式解决数据问题。我们知道,解决数据问题有很多方法:利用PySpark,我们能够为复杂的问题编写简单的代码。这正是我想通过本书表达的座右铭:保持简单并使用参数,使你的解决方案能够被其他开发人员重用。我的目标是教读者考虑数据,了解其来源和最终的预期形式,并展示如何使用基本数据转换模式解决各种数据问题。本书面向的读者为了有效地使用这本书,了解Python 编程语言的基础知识会很有帮助,例如如何使用条件语句(if-then-else)、迭代处理列表以及定义和调用函数。不过,如果你有其他编程语言背景(如Java 或Scala),还不了解Python,仍然可以使用这本书,因为我会提供Spark 和PySpark 的大量介绍。这本书主要面向那些想要分析大量数据并使用Spark 引擎和PySpark 开发分布式算法的人。我提供了一些简单的示例,会展示如何用PySpark 完成ETL 操作和编写分布式算法。我们采用了便于剪切粘贴的方式来编写这些代码示例,使你能轻松完成工作。GitHub(https://github.com/mahmoudparsian/dataalgorithms-with-spark)提供的示例代码是一个很好的资源,可以由此起步着手完成你自己的数据项目。本书内容组织本书共12 章,分为3 部分:第I 部分,基础知识。前4 章涵盖Spark 和PySpark 的基础知识,并介绍数据转换,如映射器、过滤器和归约器。这几章提供了很多实际示例,可以帮助你着手开发自己的PySpark 项目。约95% 的数据问题都可以通过使用本书前4 章介绍的简单PySpark 数据转换(如map()、flatMap()、filter() 和reduceByKey())来解决。下面详细说明这几章的内容: 第1 章,Spark 和PySpark 简介,提供了数据算法的高层概述,并介绍了如何使用Spark 和PySpark 解决数据分析问题。 第2 章,转换实战,展示了如何使用Spark 转换(映射器、过滤器和归约器)解决实际数据问题。 第3 章, 映射器转换, 介绍了最常用的映射器转换:map()、filter()、flatMap() 和mapPartitions()。 第4 章,Spark 中的归约,重点介绍归约转换(如reduceByKey()、groupByKey() 和combineByKey()),它们在按键分组数据时会发挥非常重要的作用。这一章给出了很多简单但很有用的例子,确保你能有效地使用这些归约。第II 部分,处理数据。接下来的4 章介绍数据分区、图算法、读/ 写多个不同数据源的数据,以及排名算法: 第5 章,数据分区,介绍按特定数据列对数据物理分区的函数。通过这种分区,SQL 查询(例如,Amazon Athena 或Google BigQuery 中)能分析一个数据片而不是整个数据集,这将提高查询性能。 第6 章,图算法,会介绍最重要的Spark 外部包之一:GraphFrames,可以在Spark 分布式环境中用来分析大型图。 第7 章,与外部数据源交互,会展示如何从各种不同数据源读写数据。 第8 章,排名算法,介绍了两种重要的排名算法,PageRank(用于搜索引擎)和秩序乘积(用于基因分析)。第III 部分,数据设计模式。最后4 章介绍实用的数据设计模式,我们会通过具体的例子采用一种非正式的方式展示这些设计模式: 第9 章,经典数据设计模式,将介绍常用于解决各种数据问题的一些基本数据设计模式或可重用的解决方案。例如输入- 映射- 输出和输入-过滤- 输出。 第10 章,实用数据设计模式,介绍了常见的实用数据设计模式,用于完成组合、汇总、过滤和组织数据等任务。我们会以非正式的方式介绍这些模式,并提供实际示例。 第11 章,连接设计模式,介绍连接两个或多个数据集的简单模式;为了提高连接算法的效率,这一章还会讨论一些性能准则。 第12 章,PySpark 中的特征工程,介绍了开发机器学习算法中使用的最常见的特征工程技术。额外章节因为我不希望这本书过于庞大,本书的GitHub 存储库(https://github.com/mahmoudparsian/dataalgorithms-with-spark)中还提供了额外章节,介绍关于TF-IDF、相关性和k-mers 等主题的附加内容。排版约定本书采用以下排版约定。斜体(Italic)表示新术语、URL、电子邮件地址、文件名和文件扩展名。等宽字体(Constant Width)表示程序清单,在段落内表示程序元素,例如变量、函数名称、数据库、数据类型、环境变量、语句和关键字。粗体等宽字体(Constant width bold)表示应由用户原封不动输入的命令或其他文本。斜体等宽字体(Constant width italic)表示应该替换成用户提供值的文本,或者由上下文决定的值。使用代码示例这本书的补充材料( 代码示例、练习等) 可以从https://github.com/mahmoudparsian/data-algorithms-with-spark 下载。如果使用代码示例时有技术问题或遇到其他问题,请通过以下email 联系我们:mahmoud.parsian@yahoo.com。这本书的目的就是要帮助你完成工作。一般来讲,你可以在你的程序和文档中使用这些代码,不需要联系我们来得到许可,除非你直接复制了大部分的代码。例如,如果你在编写一个程序,使用了本书中的多段代码,这并不需要得到许可。但是出售或发行OReilly 书示例代码则需要得到许可。回答问题时如果引用了这本书的文字和示例代码,这不需要得到许可。但是如果你的产品的文档借用了本书中的大量示例代码,则需要得到许可。我们希望但不严格要求标明引用出处。引用信息通常包括书名、作者、出版商和ISBN。例如Data Algorithms with Spark by Mahmoud Parsian (OReilly).Copyright 2022 Mahmoud Parsian, 978-1-492-08238-5。如果你认为你在使用代码示例时超出了合理使用范围或者上述许可范围,可以随时联系我们:permissions@oreilly.com。OReilly 在线学习平台(OReilly Online Learning)近40 年来,OReilly Media 致力于提供技术和商业培训、知识和卓越见解,来帮助众多公司取得成功。公司独有的专家和改革创新者网络通过OReilly 书籍、文章以及在线学习平台,分享他们的专业知识和实践经验。OReilly 在线学习平台按照您的需要提供实时培训课程、深入学习渠道、交互式编程环境以及来自OReilly 和其他200 多家出版商的大量书籍与视频资料。更多信息,请访问网站:https://www.oreilly.com/。联系我们任何有关本书的意见或疑问,请按照以下地址联系出版社。美国:OReilly Media, Inc.1005 Gravenstein Highway NorthSebastopol, CA 95472中国:北京市西城区西直门南大街2 号成铭大厦C 座807 室(100035)奥莱利技术咨询(北京)有限公司针对这本书,我们还建有一个网页,列出了有关勘误、示例和其他信息。可以通过以下地址访问这个页面:https://oreil.ly/data-algorithms-with-spark。如果对这本书有什么意见,或者询问技术上的问题,请发送电子邮件至errata@oreilly.com.cn。有关我们的图书和课程,更多新闻和信息请访问我们的网站:http://www.oreilly.com。我们的LinkedIn:https://linkedin.com/company/oreilly-media。我们的Twitter:http://twitter.com/oreillymedia。我们的YouTube:http://youtube.com/oreillymedia。致谢写这本书的想法是Jess Haberman(OReilly Media 高级策划编辑)提出来的。非常感谢她伸出援手。谢谢你,Jess !感谢Melissa Potter(OReilly Media 内容开发编辑),她从这个项目之初就不知疲倦地与我一同工作,她的帮助使这本书变得更好。非常感谢,Melissa !非常感谢文字编辑Rachel Head,她在整本书的编辑中做了大量工作。如果你能读懂这本书,那都是Rachel 的功劳。我想对Christopher Faucher(产品编辑)衷心说声谢谢,你出色的工作确保我们达成了最后期限,并且一切顺利。一本书付梓出版绝不是一件容易的事情,但Christopher很出色地完成了这个工作。非常感谢技术审校Parviz Deyhim 和Benjamin Muskalla 对这本书细致的审查,以及后续的评论、更正和建议。还要特别感谢我的博士导师和亲爱的朋友Ramachandran Krishnaswamy 博士,他让我学到了很多东西;我会永远珍惜与他的友谊。我在GitHub 上为所有章节提供了PySpark 解决方案,作为补充,Deepak Kumar和Biman Mandal 提供了Scala 解决方案,对读者来说这是一个很好的资源。谢谢你们,Deepak 和Biman。最后(但绝不是不重要),非常感谢Matei Zaharia 博士(Apache Spark 创始人)为这本书写了序,他的美言让我倍感荣幸。
Mahmoud Parsian,计算机科学博士,作为开发人员、设计师、架构师和作者,他是一位有30多年丰富经验的软件专业人士。在过去的15年里,他一直在从事Java服务器端计算、数据库、MapReduce、Spark和分布式计算的相关工作。Parsian博士领导了Illumina的大数据团队,专注于大规模基因组分析以及使用Spark和PySpark的分布式计算。Parsian博士还在圣克拉拉大学教授机器学习和大数据建模和分析课程。
目录
序 1
前言 3
第I 部分 基础知识
第1 章 Spark 和PySpark 简介 13
1.1 为什么使用Spark 完成数据分析 14
1.1.1 Spark 生态系统 17
1.1.2 Spark 架构 18
1.2 PySpark 的能力 .25
1.3 Spark 数据抽象 30
1.3.1 RDD 示例 31
1.3.2 Spark RDD 操作 32
1.3.3 DataFrame 示例 36
1.4 使用PySpark Shell 38
1.4.1 启动PySpark Shell .40
1.4.2 由集合创建RDD .41
1.4.3 聚合和合并键的值 .41
1.4.4 过滤RDD 的元素 43
1.4.5 对类似的键分组 44
1.4.6 聚合类似键的值 45
1.5 使用DataFrame 的ETL 示例 .46
1.5.1 抽取 47
1.5.2 转换 48
1.5.3 加载 49
1.6 小结 .50
第2 章 转换实战 51
2.1 DNA 碱基计数示例 .52
2.1.1 DNA 碱基计数问题 55
2.1.2 FASTA 格式 55
2.1.3 示例数据 .56
2.2 DNA 碱基计数解决方案1 56
2.2.1 步骤1:由输入创建一个RDD[String] 57
2.2.2 步骤2:定义一个映射器函数59
2.2.3 步骤3:得出DNA 字母频度 62
2.2.4 解决方案1 的优缺点.64
2.3 DNA 碱基计数解决方案2 65
2.3.1 步骤1:由输入创建一个RDD[String] 67
2.3.2 步骤2:定义一个映射器函数67
2.3.3 步骤3:得出DNA 字母频度 69
2.3.4 解决方案2 的优缺点.70
2.4 DNA 碱基计数解决方案3 71
2.4.1 mapPartitions() 转换 71
2.4.2 步骤1:由输入创建一个RDD[String] 79
2.4.3 步骤2:定义函数处理一个分区 .79
2.4.4 步骤3:对各个分区应用自定义函数 82
2.4.5 解决方案3 的优缺点.84
2.5 小结 .84
第3 章 映射器转换 87
3.1 数据抽象和映射器 87
3.2 转换是什么? .89
3.2.1 懒转换 94
3.2.2 map() 转换 96
3.2.3 DataFrame 映射器 102
3.3 flatMap() 转换 .105
3.3.1 map() 与flatMap() 111
3.3.2 对DataFrame 应用flatMap() 111
3.4 mapValues() 转换 115
3.5 flatMapValues() 转换 116
3.6 mapPartitions() 转换 . 118
3.6.1 处理空分区 .121
3.6.2 优缺点 125
3.6.3 DataFrame 和mapPartitions() 转换 .126
3.7 小结 129
第4 章 Spark 中的归约 131
4.1 创建(键,值)对RDD .132
4.2 归约转换.134
4.3 Spark 的归约 136
4.4 简单热身示例 139
4.4.1 使用reduceByKey() 的解决方案 140
4.4.2 使用groupByKey() 的解决方案 141
4.4.3 使用aggregateByKey() 的解决方案 142
4.4.4 使用combineByKey() 的解决方案 143
4.5 什么是Monoid ? 144
4.6 电影问题.149
4.6.1 要分析的输入数据集152
4.6.2 aggregateByKey() 转换 .153
4.6.3 使用aggregateByKey() 的第一个解决方案 .154
4.6.4 使用aggregateByKey() 的第二个解决方案 .159
4.6.5 使用groupByKey() 的完整PySpark 解决方案 161
4.6.6 使用reduceByKey() 的完整PySpark 解决方案 164
4.6.7 使用combineByKey() 的完整PySpark 解决方案 167
4.7 归约中的洗牌步骤 .170
4.7.1 groupByKey() 的洗牌步骤 172
4.7.2 reduceByKey() 的洗牌步骤 .173
4.8 小结 174
第II 部分 处理数据
第5 章 数据分区 . 179
5.1 分区简介.180
5.2 管理分区.185
5.2.1 默认分区 186
5.2.2 显式分区 187
5.3 为SQL 查询完成物理分区 188
5.4 Spark 中的数据物理分区 192
5.4.1 分区为文本格式 192
5.4.2 分区为Parquet 格式 193
5.5 如何查询分区数据 .194
5.6 小结 196
第6 章 图算法 . 199
6.1 图介绍 .200
6.2 GraphFrames API 202
6.2.1 如何使用GraphFrames .203
6.2.2 GraphFrames 函数和属性 .207
6.3 GraphFrames 算法 .207
6.3.1 查找三角形 .208
6.3.2 Motif 查找 212
6.4 实际示例.222
6.4.1 基因分析 223
6.4.2 社交推荐 224
6.4.3 Facebook 朋友圈 229
6.4.4 连通分量 234
6.4.5 分析航班数据 .236
6.5 小结 246
第7 章 与外部数据源交互 247
7.1 关系数据库 248
7.1.1 读取数据库 .249
7.1.2 将DataFrame 写入数据库 258
7.2 读取文本文件 263
7.3 读写CSV 文件 265
7.3.1 读CSV 文件 266
7.3.2 写CSV 文件 270
7.4 读写JSON 文件 272
7.4.1 读JSON 文件 .272
7.4.2 写JSON 文件 .274
7.5 读写Amazon S3 .275
7.5.1 从Amazon S3 读取 .277
7.5.2 写入Amazon S3 278
7.6 读写Hadoop 文件 280
7.6.1 读Hadoop 文本文件 281
7.6.2 写Hadoop 文本文件 284
7.6.3 读写HDFS SequenceFile .287
7.7 读写Parquet 文件 288
7.7.1 写Parquet 文件 .289
7.7.2 读Parquet 文件 .291
7.8 读写Avro 文件 292
7.8.1 读Avro 文件 292
7.8.2 写Avro 文件 293
7.9 读写MS SQL Server .294
7.9.1 写MS SQL Server 294
7.9.2 读MS SQL Server 295
7.10 读取图像文件 295
7.11 小结 297
第8 章 排名算法 . 299
8.1 秩序乘积.300
8.1.1 计算秩序乘积 .301
8.1.2 秩序乘积描述 .301
8.1.3 秩序乘积示例 .302
8.1.4 PySpark 解决方案 304
8.2 PageRank 310
8.2.1 PageRank 的迭代计算 313
8.2.2 使用RDD 的自定义PySpark PageRank 算法实现 315
8.2.3 使用邻接矩阵的自定义PySpark PageRank 算法实现 318
8.2.4 使用GraphFrames 实现的PageRank 321
8.3 小结 322
第III 部分 数据设计模式
第9 章 经典数据设计模式 327
9.1 输入?C 映射?C 输出 .328
9.1.1 RDD 解决方案 329
9.1.2 DataFrame 解决方案 332
9.1.3 扁平映射器功能 334
9.2 输入?C 过滤?C 输出 .336
9.2.1 RDD 解决方案 337
9.2.2 DataFrame 解决方案 337
9.2.3 DataFrame 过滤器 338
9.3 输入?C 映射?C 归约?C 输出 .340
9.3.1 RDD 解决方案 340
9.3.2 DataFrame 解决方案 344
9.4 输入?C 多重?C 映射?C 归约?C 输出 346
9.4.1 RDD 解决方案 348
9.4.2 DataFrame 解决方案 350
9.5 输入?C 映射?C 组合器?C 归约?C 输出351
9.6 输入?C 映射分区?C 归约?C 输出 355
9.7 倒排索引.359
9.7.1 问题陈述 360
9.7.2 输入 .360
9.7.3 输出 .360
9.7.4 PySpark 解决方案 361
9.8 小结 364
第10 章 实用数据设计模式 367
10.1 映射器内部组合 368
10.1.1 基本MapReduce 算法 .370
10.1.2 按记录映射器内部组合 372
10.1.3 按分区映射器内部组合 374
10.2 Top-10 377
10.2.1 Top-N 形式化描述 .380
10.2.2 PySpark 解决方案 .381
10.2.3 查找Bottom 10384
10.3 MinMax 385
10.3.1 解决方案1:传统MapReduce 385
10.3.2 解决方案2:排序 .386
10.3.3 解决方案 3:Spark 的mapPartitions() 386
10.4 复合模式和Monoid 390
10.4.1 Monoid 391
10.4.2 Monoid 和非Monoid 示例 395
10.4.3 非Monoid MapReduce 示例 .399
10.4.4 Monoid MapReduce 示例 401
10.4.5 Monoid 均值计算的PySpark 实现 403
10.4.6 函子和幺半群 406
10.4.7 幺半群使用小结 .408
10.5 分箱 408
10.6 排序 412
10.7 小结 413
第11 章 连接设计模式 . 415
11.1 连接操作介绍 415
11.2 MapReduce 中的连接 418
11.2.1 映射阶段 419
11.2.2 归约器阶段 420
11.2.3 PySpark 实现 421
11.3 使用RDD 的映射端连接 .422
11.4 使用DataFrame 的映射端连接 .427
11.4.1 步骤1:创建Airports 缓存 429
11.4.2 步骤2:创建Airlines 缓存 429
11.4.3 步骤3:创建事实表 .430
11.4.4 步骤4:应用映射端连接 431
11.5 使用Bloom 过滤器的高效连接 431
11.5.1 Bloom 过滤器 432
11.5.2 一个简单的Bloom 过滤器示例 434
11.5.3 Python 中的Bloom 过滤器 435
11.5.4 PySpark 中使用Bloom 过滤器 435
11.6 小结 436
第12 章 PySpark 中的特征工程 439
12.1 特征工程介绍 441
12.2 增加新特征 .443
12.3 应用UDF .444
12.4 创建管道 444
12.5 二值化数据 .447
12.6 填充 449
12.7 分词 451
12.7.1 Tokenizer 452
12.7.2 RegexTokenizer 453
12.7.3 管道分词 453
12.8 标准化 454
12.9 归一化 457
12.9.1 使用管道缩放一列 459
12.9.2 在多列上使用 MinMaxScaler 460
12.9.3 使用Normalizer 归一化 .461
12.10 字符串索引 462
12.10.1 对单列应用StringIndexer463
12.10.2 对多列应用StringIndexer464
12.11 向量组合 464
12.12 分桶 .466
12.12.1 Bucketizer 467
12.12.2 QuantileDiscretizer .468
12.13 对数转换 469
12.14 独热编码 471
12.15 TF-IDF 477
12.16 FeatureHasher .482
12.17 SQLTransformer .483
12.18 小结 .484