【博学谷学习记录】超强总结,用心分享|Spark-RDD的各类算子(一)

【博学谷学习记录】超强总结,用心分享|Spark-RDD的各类算子(一)

一、RDD算子分类

RDD算子: 指的是RDD对象中提供了非常多的具有特殊功能的函数,我们一般将这样的函数称为算子(大白话: 指的RDD的API)。
整个RDD的算子,共分为二大类:Transformation(转换算子) 和 Action(动作算子)
1.转换算子特性
(1)所有的转换算子在执行完成后,都会返回一个新的RDD;
(2)所有的转换算子都是LAZY(惰性),并不会立即执行,此时可以认为通过转换算子定义RDD的计算规则;
(3)转换算子必须遇到Action算子才会触发执行。
2.动作算子特性
(1)动作算子在执行后,不会返回一个RDD,要不然没有返回值,要不就返回其他的;
(2)动作算子都是立即执行,一个动作算子就会产生一个Job执行任务,运行这个动作算子所依赖的所有的RDD。
3.部分转换算子如图
在这里插入图片描述
4.部分动作算子如图
在这里插入图片描述

二、RDD的转换算子

(1)值类型的算子:map()

  • 格式: rdd.map(fn)
  • 说明: 根据传入的函数,对数据进行一对一的转换操作,传入一行,返回一行。
rdd = sc.parallelize([1,2,3,4,5,6,7,8,9,10])

需求: 请对每一个元素进行 +1 返回

def fn1(e):
    return e + 1

rdd.map(fn1).collect()
结果为:
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 

当一个函数中只有一行代码的时候, 可以将其改写为lambda的匿名函数
rdd.map(lambda e: e + 1).collect()
结果为:
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

(2)值类型的算子:groupBy()

  • 格式: groupBy(fn)
  • 说明: 根据传入的函数对数据进行分组操作
rdd = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
需求: 请将数据分为奇数和偶数二部分
划分奇数和偶数:2取余, 余数为 0 即为偶数 余数为1 即为奇数
def fn1(e):
    if e % 2 == 0:
        return 'o'
    else:
        return 'j'

rdd.groupBy(fn1).collect()

结果:
[
	('j', <pyspark.resultiterable.ResultIterable object at 0x7f09acefba30>), 
	('o', <pyspark.resultiterable.ResultIterable object at 0x7f09adadb910>)
]
mapValues(list): 将 kv中value转换为list类型
rdd.groupBy(fn1).mapValues(list).collect()
结果:
[
	('j', [1, 3, 5, 7, 9]), 
	('o', [2, 4, 6, 8, 10])
]
思考: 上述编写 fn1函数, 请问是否可以写成lambda, 如果可以, 这个lambda应该如何编写呢? 
rdd.groupBy(lambda e: 'o' if e % 2 == 0 else 'j' ).mapValues(list).collect()
[
	('j', [1, 3, 5, 7, 9]), 
	('o', [2, 4, 6, 8, 10])
]

(3)值类型的算子:filter()

  • 格式: filter(fn)
  • 说明: 过滤算子, 可以根据函数中指定的过滤条件, 对数据进行过滤操作, 条件返回True表示保留, 返回False 表示过滤掉
rdd = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
需求: 请将 <=3的数据过滤掉
rdd.filter(lambda num: num > 3).collect()
结果:
	[4, 5, 6, 7, 8, 9, 10]

(4)值类型的算子:flatMap()

  • 格式: flatMap(fn)
  • 说明: 在map算子的基础上, 在加入一个压扁的操作, 主要适用于一行中包含多个内容的操作, 实现一转多的操作
rdd = sc.parallelize(['张三|李四|王五|赵六','田七|周八|李九'])
需求: 将数据转换为一个个的姓名
rdd.flatMap(lambda line: line.split('|')).collect()
结果:
	['张三', '李四', '王五', '赵六', '田七', '周八', '李九']

(5)双值类型的算子:union(并集) 和 intersection(交集)

  • 格式: rdd1.union|intersection(rdd2)
rdd1 = sc.parallelize([1,4,5,2,8,6])
rdd2 = sc.parallelize([2,5,6,1,9,8])
结果:
  并集:
	rdd1.union(rdd2).collect()
	结果:
		[1, 4, 5, 2, 8, 6, 2, 5, 6, 1, 9, 8]
	去重操作:
	rdd1.union(rdd2).distinct().collect()
	结果
		[4, 8, 1, 5, 9, 2, 6]
  交集:
  	rdd1.intersection(rdd2).collect()
  	结果:
  		[8, 1, 5, 2, 6]

(6)kv类型相关的算子:groupByKey()

  • 格式: groupByKey()
  • 说明: 根据key进行分组操作
rdd = sc.parallelize([('c01','张三'),('c02','李四'),('c02','王五'),('c01','赵六'),('c01','田七'),('c02','周八'),('c03','李九')])

需求: 根据班级分组统计
rdd.groupByKey().collect()
结果:
[
	('c01', <pyspark.resultiterable.ResultIterable object at 0x7f09aced8b80>), 
	('c02', <pyspark.resultiterable.ResultIterable object at 0x7f09ace7f4f0>), 
	('c03', <pyspark.resultiterable.ResultIterable object at 0x7f09ace7f580>)
]
rdd.groupByKey().mapValues(list).collect()
结果:
[
	('c01', ['张三', '赵六', '田七']), 
	('c02', ['李四', '王五', '周八']), 
	('c03', ['李九'])
]
统计每组内有多少个数据呢?
rdd.groupByKey().mapValues(list).map(lambda kv: (kv[0],len(kv[1]))).collect()
结果:
	[('c01', 3), ('c02', 3), ('c03', 1)]

(7)reduceByKey()

  • 格式: reduceByKey(fn)
  • 说明: 根据key进行分组, 将一个组内的value数据放置到一个列表中, 对这个列表基于传入函数进行聚合计算操作
rdd = sc.parallelize([('c01','张三'),('c02','李四'),('c02','王五'),('c01','赵六'),('c01','田七'),('c02','周八'),('c03','李九')])
需求: 统计每个班级有多少个人
rdd.map(lambda kv: (kv[0],1)).reduceByKey(lambda agg,curr: agg + curr).collect()
[('c01', 3), ('c02', 3), ('c03', 1)]
如果不转换, 请问会出现什么结果呢?
('c01','张三') ('c01','赵六'),('c01','田七')
rdd.reduceByKey(lambda agg,curr: agg + curr).collect()
结果:
	[('c01','张三赵六田七'),('c02','李四王五周八'),('c03','李九')]

(8)sortByKey()

  • 格式: sortByKey(ascending=True|False 默认为True)
  • 说明: 根据key进行排序操作, 默认按照key进行升序排序, 如果需要倒序 设置ascending为False
rdd = sc.parallelize([('c05','张三'),('c02','李四'),('c07','王五'),('c01','赵六'),('c03','田七'),('c08','周八'),('c04','李九')])
根据班级的序号进行排序操作
rdd.sortByKey().collect()
结果:
[('c01', '赵六'), ('c02', '李四'), ('c03', '田七'), ('c04', '李九'), ('c05', '张三'), ('c07', '王五'), ('c08', '周八')]
倒序排列:
rdd.sortByKey(ascending=False).collect()
结果:
[('c08', '周八'), ('c07', '王五'), ('c05', '张三'), ('c04', '李九'), ('c03', '田七'), ('c02', '李四'), ('c01', '赵六')]
rdd = sc.parallelize([('c2','张三'),('c11','李四'),('c21','王五'),('c3','赵六'),('c1','田七'),('c08','周八'),('c04','李九')])
rdd.sortByKey(ascending=False).collect()
结果: 字典序, 因为 key是字符串
	[('c3', '赵六'), ('c21', '王五'), ('c2', '张三'), ('c11', '李四'), ('c1', '田七'), ('c08', '周八'), ('c04', '李九')]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值