大数据学习-Spark算子(一)之基本RDD操作

Spark算子(一)之基本RDD操作

参考书籍《大数据技术与应用》肖政宏 李俊杰 谢志明 编著

Spark算子大致分为转化(Transformation)和行动(Action)两类。

1)Transformation:不触发提交作业,完成作业中间过程处理。

函数包括:map、filter、flatMap、groupByKey、aggregateByKey、pipe和coalesce等。

2)Action:会触发SparkContext提交作业(job)。

函数包括:reduce、collect、count、first、take、countByKey和foreach等。

以下用python进行编写

1、基本RDD的转化操作

1)map(func)

将func函数作用到RDD的每个元素,生成一个新的RDD返回。

计算rdd1中个元素值的平方。

>>> rdd1 = sc.parallelize([1,2,3,4,5])
>>> rdd2 = rdd1.map(lambda x:x*x).collect()
>>> print(rdd2)
[1, 4, 9, 16, 25]

2)flatMap(func)

与map相似,但是每个输入的item能够被map到0个或者更多的items输出。

将rdd1中元素数据切分为单词

>>> lst = ['i am one','he is two','she is three']
>>> rdd1 = sc.parallelize(lst,3)
>>> rdd2 = rdd1.flatMap(lambda x:x.split()).collect()
>>> print(rdd2)
['i', 'am', 'one', 'he', 'is', 'two', 'she', 'is', 'three']

3)filter(func)

选出所有func返回值为true的元素,作为一个新的RDD返回。

过滤rdd1中的值不是2的元素

>>> rdd1 = sc.parallelize([1,2,3,4,5,6])
>>> rdd2 = rdd1.filter(lambda x:x!=2).collect()
>>> print(rdd2)
[1, 3, 4, 5, 6]

4)mapPartitions(func)

与map相似,但是mapPartition的输入函数单独作用于RDD的每个分区(block)上,因此func的输入和返回值都必须是迭代器iterator。

假设rdd1有0~9共10个元素,分成3个区,使用mapPartitions返回每个元素的平方。如果使用map方法,map中的输入函数会被调用10次;而使用mapPartitions方法,输入函数只会被调用3次,每个分区被调用一次。

>>> def Func(a):
...     for i in a:
...             yield i * i
... 
>>> rdd1 = sc.parallelize(range(10),3)
>>> rdd2 = rdd1.mapPartitions(Func).collect()
>>> print(rdd2)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

5)mapPartitionsWithIndex(func)

与mapPartitions相似,但是输入函数func提供了一个正式的参数,可以用来表示分区的编号。

对rdd1的分区进行求和

>>> def func(index,iterator):
...     yield(index,sum(iterator))
... 
>>> rdd1 = sc.parallelize(range(10),3)
>>> rdd2 = rdd1.mapPartitionsWithIndex(func)
>>> print(rdd1.collect())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(rdd2.collect())
[(0, 3), (1, 12), (2, 30)]
>>> print(rdd1.glom().collect())
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> print(rdd2.glom().collect())
[[(0, 3)], [(1, 12)], [(2, 30)]]

sc的glom()方法的作用是将同一个分区里的元素合并到一个array里


6)distinct([numTasks])

删除RDD中相同的元素

删除rdd1中相同的元素

>>> rdd1 = sc.parallelize([1,1,2,5,2,9,6,1])
>>> rdd2 = rdd1.distinct().collect()
>>> print(rdd2)          
[1, 2, 5, 6, 9]

7)sample(withReplacement,fraction,seed)

以指定的种子有放回或者无放回随机抽样。

withReplaceement:true为有放回的抽样,false为无放回

fraction:

​ 当withReplaceement = true时,fraction为大于等于0的数,表示选择每个元素的期望次数;

​ 当withReplaceement = false时,fraction为选择每个元素的概率,范围为[0,1]

seed:随机种子

>>> rdd1 = sc.parallelize(range(20))
>>> rdd2 = rdd1.sample(False,0.5)
>>> print(rdd2.collect())
[1, 2, 5, 6, 9, 14, 16, 19]

8)cartesian(otherDataset)

对两个RDD内的所有元素进行笛卡尔积操作。

>>> rdd1 = sc.parallelize([('a',1),('a',2)])
>>> rdd2 = sc.parallelize([('c',3),('d',4)])
>>> rdd3 = rdd1.cartesian(rdd2).collect()
>>> print(rdd3)
[(('a', 1), ('c', 3)), (('a', 1), ('d', 4)), (('a', 2), ('c', 3)), (('a', 2), ('d', 4))]

9)union(otherDataset)

合并两个RDD元素,两个RDD元素的数据类型要相同。

合并rdd1和rdd2。

>>> rdd1 = sc.parallelize([('a',1),('a',2)])
>>> rdd2 = sc.parallelize([('c',3),('d',4)])
>>> rdd3 = rdd1.union(rdd2).collect()
>>> print(rdd3)
[('a', 1), ('a', 2), ('c', 3), ('d', 4)]

10)intersection(otherDataset)

对两个RDD内的所有元素提取交集。

计算rdd1和rdd2的交集

>>> rdd1 = sc.parallelize(range(10))
>>> rdd2 = sc.parallelize(range(6,15))
>>> rdd3 = rdd1.intersection(rdd2).collect()
>>> print(rdd1.collect())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(rdd2.collect())
[6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> print(rdd3)
[6, 8, 7, 9]

11)subtract(otherDataset)

进行集合的差操作。

rdd1去除rdd1和rdd2交集中的所有元素。

>>> rdd1 = sc.parallelize(range(10))
>>> rdd2 = sc.parallelize(range(6,15))
>>> rdd3 = rdd1.subtract(rdd2).collect()
>>> print(rdd3)
[0, 2, 4, 1, 3, 5]

2、基本RDD的行动操作

1)collect()

返回RDD中的所有元素。

显示rdd1中的所有元素。

>>> rdd1 = sc.parallelize(range(10))
>>> print(rdd1.collect())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

2)count()

返回RDD中的元素个数。

计算rdd1中的元素个数。

>>> rdd1 = sc.parallelize(range(10))
>>> print(rdd1.count())
10

3)countByValue()

返回RDD中的各元素出现的次数。

计算rdd1中各元素出现的次数

>>> rdd1 = sc.parallelize([1,2,2,3,'a','a'])
>>> print(rdd1.countByValue())
defaultdict(<type 'int'>, {'a': 2, 1: 1, 2: 2, 3: 1})

4)take(num)

返回RDD前num个元素。

取rdd1中前3个元素。

>>> rdd1 = sc.parallelize(range(10))
>>> print(rdd1.take(3))
[0, 1, 2]

5)top(num)

返回RDD最大的num个元素。

取rdd1中最大的3个元素。

>>> rdd1 = sc.parallelize(range(10))
>>> print(rdd1.top(3))
[9, 8, 7]

6)takeOrdered(num)

返回RDD中最小的num个元素。

取rdd1中最小的3个元素

>>> rdd1 = sc.parallelize(range(10))
>>> print(rdd1.takeOrdered(3))
[0, 1, 2]

7)takeSample(withReplacement,num,seed)

takesample函数类似于sample函数。

withReplacement:True表示有放回抽样,False表示无放回。

num:表示返回的采样数据的个数。

seed:表示用于指定的随机数生成器种子。

从rdd1中随机且有放回地抽出10个数据,随机种子值为5。

>>> rdd1 = sc.parallelize(range(20))
>>> rdd2 = rdd1.takeSample(True,10,5)
>>> print(rdd2)
[18, 9, 17, 4, 5, 11, 11, 9, 4, 9]

8)reduce(func)

将RDD中元素两两传递给输入函数,同时产生一个新值;新产生的值与RDD中下一个元素再被传递给输入函数,直到最后只有一个值为止。

对rdd1中的元素求和。

>>> rdd1 = sc.parallelize(range(20))
>>> sum = rdd1.reduce(lambda x,y:x+y)
>>> print(sum)
190

9)fold(zero,func)

和reduce一样,但是需要提供初始值。

对rdd1中的元素加上初始值求和。

>>> rdd1 = sc.parallelize([1,2,3,4,5])
>>> def func(x,y):
...     return x+y
>>> sum = rdd1.fold(1,func)
>>> print(sum)
17

#通过在func函数里加入
#...     print(x,y,x+y)
#我们可以得到运算过程
#(1, 1, 2)
#(2, 2, 4)
#(4, 3, 7)
#(7, 4, 11)
#(11, 5, 16)
#(1, 16, 17)
#可以分析出分别在第一次和最后一次运算中加了初始值1

10)aggregate(zeroValue,seqOp,combOp)

zeroValue:初始值

seqOp:对每个分区进行操作

combOp:combine对每个分区的结果进行操作

>>> rdd1 = sc.parallelize([1,2,3,3],2)
>>> seqOp = lambda x,y:(x[0] + y,x[1] + 1)
>>> combOp = lambda x,y:(x[0] + y[0],x[1] + y[1])
>>> rdd2 = rdd1.aggregate((0,0),seqOp,combOp)
>>> print(rdd2)
(9, 4)

过程说明:

seqOp对第一个分区(同时并行的对第二个分区进行同样的操作)进行操作步骤是

开始先用初始值和第一个分区的第一个值,然后是结果和其余的值进行操作

0+1,0+1
1+2,1+1
结果是(3,2),同样的第二个分区的结果是(6,2)

combOp对两个分区的结果以及初始值本身进行操作

(3+9,2+2)


11)foreach(func)

对RDD中的每个元素使用给定的函数。

打印rdd1中的元素。

>>> def prn(x):print(x),;print(''),
>>> rdd1 = sc.parallelize([1,2,3,3])
>>> rdd1.foreach(prn)
1 2 3 3

大数据学习-Spark算子(二)之Pair RDD操作
大数据学习-Spark算子(三)之RDD的其他操作

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值