PySpark大数据分析(2):RDD操作

RDD基础

在Spark中,数据以弹性分布式数据集(Resilient Distributed Dataset)的形式存在。对RDD的操作主要分为转化操作和行动操作两种。Spark可以将RDD中的数据分发到集群上,以此并行化执行相关的操作。

最直接的创建方式就是通过SprakContext的parallelize()方法,将一个已有集合变为RDD:

>>> lines = sc.parallelize(['word1', 'word2', 'word3'])

当我们读取一个外部数据的时候,它在Spark中就是以RDD的形式存在的。比如我们读取一个Iris数据集:

>>> iris = spark.read.csv('/Users/data/iris.csv', header=True)
>>> iris.show(5)
+------------+-----------+------------+-----------+-----------+
|Sepal Length|Sepal Width|Petal Length|Petal Width|      Label|
+------------+-----------+------------+-----------+-----------+
|         5.1|        3.5|         1.4|        0.2|Iris-setosa|
|         4.9|        3.0|         1.4|        0.2|Iris-setosa|
|         4.7|        3.2|         1.3|        0.2|Iris-setosa|
|         4.6|        3.1|         1.5|        0.2|Iris-setosa|
|         5.0|        3.6|         1.4|        0.2|Iris-setosa|
+------------+-----------+------------+-----------+-----------+
only showing top 5 rows

此时的iris就是一个RDD。接下来分别对这个RDD进行转化操作以及求值操作。

RDD操作

RDD的转化操作会返回一个新的RDD,比如之前用来进行条件过滤的filter()。行动操作指的是操作结果需要返回给驱动器或者写入外部系统,比如count()。一般返回值为RDD的操作都是转化操作,返回值是其他类型的操作是行动操作。

转化操作

RDD一旦创建就无法修改。因此转化操作并不会影响到原本的RDD,它只会产生一个新的RDD。因此需要一个的变量去接收这个RDD,或者直接将结果覆盖到原始RDD上。比如修改iris的列名,调用withColumnRenamed()修改列名之后,需要将结果覆盖到iris上。如果我们想筛选出Label为“Iris-setosa”,同时花萼宽度为3.1的数据,我们需要一个新的变量来接收filter()针对两个条件进行过滤的结果:

>>> iris = iris.withColumnRenamed('Sepal Width', 'Sepal_Width')
>>> setosa = iris.filter((iris.Label == 'Iris-setosa') & (iris.Sepal_Width == 3.1))
>>> setosa.show(5)
+------------+-----------+------------+-----------+-----------+
|Sepal Length|Sepal_Width|Petal Length|Petal Width|      Label|
+------------+-----------+------------+-----------+-----------+
|         4.6|        3.1|         1.5|        0.2|Iris-setosa|
|         4.9|        3.1|         1.5|        0.1|Iris-setosa|
|         4.8|        3.1|         1.6|        0.2|Iris-setosa|
|         4.9|        3.1|         1.5|        0.1|Iris-setosa|
|         4.9|        3.1|         1.5|        0.1|Iris-setosa|
+------------+-----------+------------+-----------+-----------+

转化操作可以一次对多个RDD进行操作,比如使用union()对两个RDD取交集:

>>> versicolor = iris.filter(iris.Label == 'Iris-versicolor')
>>> virginica = iris.filter(iris.Label == 'Iris-virginica')
>>> vers_and_virg = versicolor.union(virginica)

转化操作会基于已有RDD生成新的RDD,Spark会使用血缘图(lineage graph)记录这个过程中的依赖关系。血缘图可以用于优化Spark的工作流程,同时也可以在持久化的RDD丢失部分数据时进行恢复。

之所以要区分转化操作和行动操作,很重要的一个原因是Spark对RDD的转化操作都是惰性求值的。比如上面的操作中,只有在show()运行时,Spark才会执行之前基于iris的所有转化操作。如果用户有多个转化操作,Spark会将这些操作的相关信息都记录下来,在需要执行的时候一起执行。因此,惰性求值可以将一些操作进行合并,从而减少计算数据的步骤。从这个角度来看,RDD其实更应该被看作一种数据的“转化操作计划”,而不是一个数据集。

行动操作

行动操作会将最终的结果返回给驱动器,或者写入外部的存储系统。因此行动操作会在计算时,运行它所依赖的所有转化操作。

比如对之前通过转化操作生成的RDD进行行数统计:

>>> vers_and_virg.count()
100

每一次的行动操作都会重新计算RDD,因此最好将需要复用的中间结果持久化。

上一篇:PySpark大数据分析(1):Spark的安装与文件读取
下一篇:PySpark大数据分析(3):使用Python操作RDD

你可能感兴趣的:(大数据处理,大数据,数据分析,Spark,Python,RDD)