【Python】PySpark 入门

简介: 【Python】PySpark 入门

1 Resilient Distributed Datasets(RDD)


弹性分布式数据集(RDD)是一个不可变的JVM对象的分布式集合,是Spark的基本抽象。


1.1 创建RDD


准备工作:

>>> import pyspark
>>> from pyspark import SparkContext
>>> from pyspark import SparkConf
>>> conf = SparkConf().setAppName('project1').setMaster('local')
>>> sc = SparkContext.getOrCreate(conf)


在PySpark里有两种方法创建RDD:

一是,.parallelize(…) 个collection集合 ( list or an array of some elements)。

>>> data = sc.parallelize([('amber',22),('alfred',23),('skye',4),('albert',12),('amber',9)])


二是,引用位于本地或HDFS上的某个文件(或多个文件)。

>>> data_from_file = sc.textFile('/home/qml/pyspark-ex/VS14MORT.txt.gz',4)
# sc.textFile(...,n)中的最后一个参数指定数据集被分区的数量,经验是分成两个四分区


# sc.textFile(…,n)中的最后一个参数指定数据集被分区的数量,经验是分成两个四分区


Spark 支持多种数据格式:可以使用JDBC驱动程序读取文本,Parquet,JSON,Hive表和来自关系数据库的数据。请注意,Spark可以自动处理压缩的数据集(如Gzip压缩数据集)。


从文件读取的数据表示为MapPartitionsRDD,而不是像当我们.paralellize(…)一个集合的数据一样表示为ParallelCollectionRDD。


1.2 Schema


RDD是无模式的数据结构(不像DataFrames)。因此,在使用RDD时,并行化数据集对于Spark来说是完美的。

>>> data_heterogenous = sc.parallelize([('Ferrari','fast'),{'Porsche':100000},['Spain','visited',4504]]).collect()


所以,我们可以混合几乎任何东西:一个元组,一个字典,或一个列表。


一旦你.collect()数据集(即,运行一个动作将其返回给驱动程序),你可以像在Python中通常那样访问对象中的数据:

>>> data_heterogenous[1]['Porsche']
100000


.collect()方法将RDD的所有元素返回到驱动程序,并将其作为列表序列化。


1.3 读取文件


从文本文件读取时,文件中的每一行形成RDD的一个元素。 可以创建一个元素列表,每行代表一个值列表。

>>> data_from_file.take(1)
[u'                   1                                          2101  M1087 432311  4M4                2014U7CN                                    I64 238 070   24 0111I64                                                                                                                                                                           01 I64                                                                                                  01  11                                 100 601']


1.4 Lambda表达式


1.4.1 Transformations


.map(…)


该方法应用于RDD的每个元素。

In [1]:
data_2014_2 = data_from_file_conv.map(lambda row: (row[16], int(row[16])))
data_2014_2.take(10)
Out[2]:
[('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('2014', 2014),
 ('-99', -99)]


.filter(…)


允许选择符合指定条件的数据集元素。

data_filtered = data_from_file_conv.filter(lambda row: row[5] == 'F' and row[21] == '0')
data_filtered.count()
1
2
.flatMap(…)
与map()的工作方式类似,但返回的是平铺的结果而不是列表。
In [3]:
data_2014_flat = data_from_file_conv.flatMap(lambda row: (row[16], int(row[16]) + 1))
data_2014_flat.take(10)
Out[4]:
['2014', 2015, '2014', 2015, '2014', 2015, '2014', 2015, '2014', 2015]


.distinct()


此方法返回指定列中不同值的列表。

In [5]:
distinct_gender = data_from_file_conv.map(lambda row: row[5]).distinct().collect()
distinct_gender
Out[6]:
['-99', 'M', 'F']


.sample(…)


该方法返回数据集中的随机样本。

In [7]:
fraction = 0.1
data_sample = data_from_file_conv.sample(False, fraction, 666)
data_sample.take(1)
Out[8]:
[array(['1', '  ', '5', '1', '01', 'F', '1', '082', ' ', '42', '22', '10',
        '  ', '4', 'W', '5', '2014', 'U', '7', 'C', 'N', ' ', ' ', 'I251',
        '215', '063', '   ', '21', '02', '11I350 ', '21I251 ', '       ',
        '       ', '       ', '       ', '       ', '       ', '       ',
        '       ', '       ', '       ', '       ', '       ', '       ',
        '       ', '       ', '       ', '       ', '       ', '02',
        'I251 ', 'I350 ', '     ', '     ', '     ', '     ', '     ',
        '     ', '     ', '     ', '     ', '     ', '     ', '     ',
        '     ', '     ', '     ', '     ', '     ', '     ', '28', ' ',
        ' ', '2', '4', '100', '8'], 
       dtype='<U40')]


.leftOuterJoin(…)


左外连接就像SQL一样,根据两个数据集中的值加入两个RDD,并从左RDD中返回从右侧追加两个RDD匹配的记录。

>>> rd1 = sc.parallelize([('a',1),('b',4),('c',10)])
>>> rd2 = sc.parallelize([('a',4),('a',1),('b','6'),('d',15)])
>>> rd3 = rd1.leftOuterJoin(rd2)
>>> print rd3.take(5)
[('a', (1, 4)), ('a', (1, 1)), ('c', (10, None)), ('b', (4, '6'))]


如果我们使用.join(…)方法,那么当这两个值在这两个RDD之间相交时,我们只能得到’a’和’b’的值。

>>> rd4 = rd1.join(rd2)
>>> print rd4.collect()
[('a', (1, 4)), ('a', (1, 1)), ('b', (4, '6'))]


另一个有用的方法是.intersection(…),它返回两个RDD中相同的记录。

>>> rd5 = rd1.intersection(rd2)
>>> print rd5.collect()
[('a', 1)]


该方法从单个数据分区返回n个最高行。

In [9]:
data_first = data_from_file_conv.take(1)
data_first
Out[10]:
[array(['1', '  ', '2', '1', '01', 'M', '1', '087', ' ', '43', '23', '11',
        '  ', '4', 'M', '4', '2014', 'U', '7', 'C', 'N', ' ', ' ', 'I64 ',
        '238', '070', '   ', '24', '01', '11I64  ', '       ', '       ',
        '       ', '       ', '       ', '       ', '       ', '       ',
        '       ', '       ', '       ', '       ', '       ', '       ',
        '       ', '       ', '       ', '       ', '       ', '01',
        'I64  ', '     ', '     ', '     ', '     ', '     ', '     ',
        '     ', '     ', '     ', '     ', '     ', '     ', '     ',
        '     ', '     ', '     ', '     ', '     ', '     ', '01', ' ',
        ' ', '1', '1', '100', '6'], 
       dtype='<U40')]


.reduce(…)

>>> rd1.map(lambda row: row[1]).reduce(lambda x,y:x+y)
15


.reduceByKey(…)

>>> data_key = sc.parallelize([('a', 4),('b', 3),('c', 2),('a', 8),('d', 2),('b', 1),('d', 3)],4)
>>> data_key.reduceByKey(lambda x, y: x + y).collect()
[('b', 4), ('c', 2), ('a', 12), ('d', 5)]


.count()


统计RDD中元素的数量。

>>> data_reduce.count()
6


.countByKey()


如果你的数据集是键值的形式,则可以使用.countByKey()方法获取不同键的数量。

>>> data_key.countByKey().items()
[('a', 2), ('b', 2), ('d', 2), ('c', 1)]


.saveAsTextFile(…)


将RDD保存到文本文件:每个分区保存到一个单独的文件。

>>> data_key.saveAsTextFile('/Users/drabast/Documents/PySpark_Data/data_key.txt')


.foreach(…)


一种将函数应用同到RDD每个元素的迭代法。

def f(x): 
    print(x)
data_key.foreach(f)


目录
相关文章
|
9月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
1016 7
|
10月前
|
测试技术 开发者 Python
Python单元测试入门:3个核心断言方法,帮你快速定位代码bug
本文介绍Python单元测试基础,详解`unittest`框架中的三大核心断言方法:`assertEqual`验证值相等,`assertTrue`和`assertFalse`判断条件真假。通过实例演示其用法,帮助开发者自动化检测代码逻辑,提升测试效率与可靠性。
624 1
|
11月前
|
API 数据安全/隐私保护 开发者
Python自定义异常:从入门到实践的轻松指南
在Python开发中,自定义异常能提升错误处理的精准度与代码可维护性。本文通过银行系统、电商库存等实例,详解如何创建和使用自定义异常,涵盖异常基础、进阶技巧、最佳实践与真实场景应用,助你写出更专业、易调试的代码。
362 0
|
11月前
|
IDE 开发工具 数据安全/隐私保护
Python循环嵌套:从入门到实战的完整指南
循环嵌套是Python中处理多维数据和复杂逻辑的重要工具。本文通过实例讲解嵌套循环的基本用法、常见组合、性能优化技巧及实战应用,帮助开发者掌握其核心思想,避免常见错误,并探索替代方案与进阶方向。
700 0
|
9月前
|
Cloud Native 算法 API
Python API接口实战指南:从入门到精通
🌟蒋星熠Jaxonic,技术宇宙的星际旅人。深耕API开发,以Python为舟,探索RESTful、GraphQL等接口奥秘。擅长requests、aiohttp实战,专注性能优化与架构设计,用代码连接万物,谱写极客诗篇。
1864 1
Python API接口实战指南:从入门到精通
|
Python
Python字符串格式化利器:f-strings入门指南
Python字符串格式化利器:f-strings入门指南
635 80
|
9月前
|
存储 Java 调度
Python定时任务实战:APScheduler从入门到精通
APScheduler是Python强大的定时任务框架,通过触发器、执行器、任务存储和调度器四大组件,灵活实现各类周期性任务。支持内存、数据库、Redis等持久化存储,适用于Web集成、数据抓取、邮件发送等场景,解决传统sleep循环的诸多缺陷,助力构建稳定可靠的自动化系统。(238字)
1598 1
|
10月前
|
调度 数据库 Python
Python异步编程入门:asyncio让并发变得更简单
Python异步编程入门:asyncio让并发变得更简单
495 5
|
10月前
|
数据采集 存储 XML
Python爬虫入门(1)
在互联网时代,数据成为宝贵资源,Python凭借简洁语法和丰富库支持,成为编写网络爬虫的首选。本文介绍Python爬虫基础,涵盖请求发送、内容解析、数据存储等核心环节,并提供环境配置及实战示例,助你快速入门并掌握数据抓取技巧。

推荐镜像

更多