1:针对各个元素的转化操作
最常用的map()和filter():map()函数接收一个函数,把这个函数用于RDD的每个元素,将函数的返回结果作为结果RDD中对应元素的值。filter()接收一个函数,并将RDD中满足该函数的元素放入新的RDD中返回。
计算RDD中各值的平方
from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
nums = sc.parallelize([1,2,3,4])
squared = nums.map(lambda x : x * x).collect()
for num in squared:
print(num)
filter()
from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
nums = sc.parallelize([1,2,3,4])
squared = nums.filter(lambda x : x > 2).collect()
for num in squared:
print(num)
#3
#4
flatMap():将函数应用到RDD中的每个元素,将返回的迭代器的所有内容构成新的RDD。通常用来切分单词
from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
words = sc.parallelize(["hello word","hi"])
word = words.flatMap(lambda line : line.split(" "))
word.foreach(print)
#hello
#word
#hi
flatMap()和Map()的区别:
2:伪集合操作
尽管RDD本身不是严格意义上的集合,但它也支持许多数学上的集合操作。
对数据分别为{1,2,3}和{3,4,5}的RDD进行针对两个RDD的转化操作
函数名 | 目的 | 示例 | 结果 |
union() | 生成一个包含RDD中所有元素的RDD | rdd.union(other) | {1,2,3,4,5} |
interection() | 求两个RDD共同的元素RDD | rdd.intersection(other) | {3} |
subtract() | 移除一个RDD中内容 | rdd.subtract(other) | {1,2} |
cartesian() | 与另一个的笛卡儿积 | rdd.cartesian(other) | {(1,3),(1,4),...(3,5)} |
3:行动操作
对一个数据为{1,2,3,3}的RDD进行基本的RDD行动操作。
函数名 |
目的 |
示例 |
结果 |
collect() |
返回RDD中的所有元素 |
Rdd.collect() |
{1,2,3,3} |
count() |
RDD中的元素个数 |
Rdd.count() |
4 |
take(num) |
从RDD中返回num个元素 |
rdd.take(2) |
{1,2} |
top(num) |
从RDD中返回最前面的num个元素 |
Rdd.top(2) |
{3,3} |
takeOrdered(num)(ordering) |
从RDD中按照提供的顺序返回最前的num个元素 |
Rdd.takeOrdered(2)(myOrdering) |
{3,3} |
reduce(func) |
并行整合RDD中所有数据 |
Rdd.reduce(lambda x ,y : x+y) |
9 |
fold(zero)(func) |
和reduce一样,但是需要提供初始值 |
Rdd.fold(2)(lambda x,y :x+y) |
9 |
aggregate(zeroValue)(seq0p,comb0p) |
和reduce相似,但是通常返回不同类型的函数 |
Rdd.aggregate((0,0)) |
(9,4) |
foreach(func) |
对RDD中的每个元素使用给定的函数 |
Rdd.foreach(func) |
无 |
SparkRDD时惰性求值的,而有时我们希望多次使用同一个RDD。如果简单地对RDD调用行动操作,Spark每次都会重算RDD以及它的所有依赖,这在迭代算法中常常会多次使用同一组数据,为了避免多次计算同一个RDD,可以让Spark对数据进行持久化。当我们让Spark持久化存储一个RDD时,计算出RDD的节点会分别保存他们所有求出的分区数据。如果一个有持久化数据的节点发生故障,Spark会在需要的时候用到缓存的数据时重新计算丢失的分区
from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
list = ["Hadoop","Spark","Hive"]
rdd = sc.parallelize(list)
rdd.cache() #会调用persist(MEMORY_ONLY),但是,语句执行到这里,并不会缓存rdd,这是rdd还没有被计算生成
print(rdd.count()) #第一次行动操作,触发一次真正从头到尾的计算,这时才会执行上面的rdd.cache(),把这个rdd放到缓存中
print(','.join(rdd.collect())) #第二次行动操作,不需要触发从头到尾的计算,只需要重复使用上面缓存中的rdd
持久化的级别
在实际编程中,我们经常需要把RDD中的元素打印输出到屏幕上(标准输出stdout),一般会采用语句rdd.foreach(print)或者rdd.map(print)。当采用本地模式(local)在单机上执行时,这些语句会打印出一个RDD中的所有元素。但是,当采用集群模式执行时,在worker节点上执行打印语句是输出到worker节点的stdout中,而不是输出到任务控制节点Driver Program中,因此,任务控制节点Driver Program中的stdout是不会显示打印语句的这些输出内容的。为了能够把所有worker节点上的打印输出信息也显示到Driver Program中,可以使用collect()方法,比如,rdd.collect().foreach(print),但是,由于collect()方法会把各个worker节点上的所有RDD元素都抓取到Driver Program中,因此,这可能会导致内存溢出。因此,当你只需要打印RDD的部分元素时,可以采用语句rdd.take(100).foreach(print)。