Spark RDD各种算子样例代码

文章详细介绍了在Anaconda环境下使用PySpark进行大数据处理时,RDD(弹性分布式数据集)的常用算子,包括map、flatMap、reduceByKey、mapValues等,并通过实例展示了这些算子在数据处理中的应用,如WordCount的经典例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Anaconda前置环境执行的代码

#初始化上下文
import findspark
findspark.init()


from  pyspark import SparkConf,SparkContext

# conf=SparkConf().setMaster("local[*]").setAppName("test")
conf=SparkConf().setAppName("test").setMaster("local[*]")
sc=SparkContext(conf=conf)

#本地文件路径
path="file:///app/notebook/testdata/"

RDD算子

分布式对象的方法就是算子;
本地对象的方法叫函数或者方法

  • 转换算子: 转换完还是RDD对象,比如map, flatMap等
  • 行为算子: 转换完不是RDD对象,比如rdd.collect()是一个list对象

第一个算子: map算子

-> rdd.map(func) 作用是将RDD的数据一条条的处理,基于func函数返回新的RDD
func是一个函数 lanbda 也可以

rdd=sc.parallelize([1,2,3,4,5,6])

def mul(data):
    return data*100

#方式1   lambda适合一行表达式
print(rdd.map(lambda x:x*100).collect())
#也可以返回一个元组
print(rdd.map(lambda x:(2,x*100)).collect())

#方式2   方法可以写多行进行复杂的运算
print(rdd.map(mul).collect())

[100, 200, 300, 400, 500, 600]
[(2, 100), (2, 200), (2, 300), (2, 400), (2, 500), (2, 600)]
[100, 200, 300, 400, 500, 600]

第二个算子: flatMap算子

作用是:解除嵌套 ; 二维数组变一维数组

rdd=sc.parallelize(["hadoop spark hadoop ","flink spark hadoop ","hadoop spark flink "])
print("map的结果是二维数组:",rdd.map(lambda x:x.split(" ")).collect())

print("flatMap直接是一维数组(解除嵌套):",rdd.flatMap(lambda x:x.split(" ")).collect())

map的结果是二维数组: [['hadoop', 'spark', 'hadoop', ''], ['flink', 'spark', 'hadoop', ''], ['hadoop', 'spark', 'flink', '']]
flatMap直接是一维数组(解除嵌套): ['hadoop', 'spark', 'hadoop', '', 'flink', 'spark', 'hadoop', '', 'hadoop', 'spark', 'flink', '']

第三个算子:reduceByKey算子, 针对KV型的RDD,可按key分组按val做聚合

rdd.reduceByKey(func)
func:(V,V) ->V 两个入参类型一直,返回的值的类型也一致

rdd=sc.parallelize([('a',1),('a',2),('a',3),('c',1),('c',1),('b',2),('b',1),('d',10)])

#写函数是为了打印a,b的值,看看a,b的计算流程
def mByKeyPara(a,b):
#     print(a,b)
    return a+b
# 相当于sum求和;   #理解里面(a+b)的运算逻辑
print(rdd.reduceByKey(mByKeyPara).collect())

#同
print(rdd.reduceByKey(lambda a,b:a+b).collect())

[('c', 2), ('b', 3), ('d', 10), ('a', 6)]
[('c', 3), ('b', 6), ('d', 10), ('a', 20)]

第四个算子:mapValues算子, 只针对map中value进行计算的

rdd=sc.parallelize([('a',2),('a',3),('c',5),('b',8),('d',10)])

# 使用map也可以实现, 看着复杂,可以改成mapValues
print(rdd.map(lambda x:(x[0],x[1]*10)).collect())

#mapValues只针对二元组中的val计算
print(rdd.mapValues(lambda x:x*10).collect())


[('a', 20), ('a', 30), ('c', 50), ('b', 80), ('d', 100)]
[('a', 20), ('a', 30), ('c', 50), ('b', 80), ('d', 100)]

回顾WordCount中的算子

file_rdd = sc.textFile("/word.txt")
print("\n文件内容:\n",file_rdd.collect())

#将单词进行切割, flatMap直接就是一维数组
words_rdd=file_rdd.flatMap(lambda line: line.split(" "))
print("\n将单词进行切割:\n",words_rdd.collect())

# 将单词转换为元组形象, key是单词,value是1
words_with_one_rdd = words_rdd.map(lambda x: (x,1))
print("\n将单词转换为元组形象:\n",words_with_one_rdd.collect())

# 将元组的value 按照key来分组
result_rdd = words_with_one_rdd.reduceByKey(lambda a,b: a + b)
print("\n将元组的value 按照key来分组:\n",result_rdd.collect())



文件内容:
 ['itheima itcast itheima itcast', 'hadoop hdfs hadoop hdfs', 'hadoop mapreduce hadoop yarn', 'itheima hadoop itcast hadoop', 'itheima itcast hadoop yarn mapreduce', '', '']

将单词进行切割:
 ['itheima', 'itcast', 'itheima', 'itcast', 'hadoop', 'hdfs', 'hadoop', 'hdfs', 'hadoop', 'mapreduce', 'hadoop', 'yarn', 'itheima', 'hadoop', 'itcast', 'hadoop', 'itheima', 'itcast', 'hadoop', 'yarn', 'mapreduce', '', '']

将单词转换为元组形象:
 [('itheima', 1), ('itcast', 1), ('itheima', 1), ('itcast', 1), ('hadoop', 1), ('hdfs', 1), ('hadoop', 1), ('hdfs', 1), ('hadoop', 1), ('mapreduce', 1), ('hadoop', 1), ('yarn', 1), ('itheima', 1), ('hadoop', 1), ('itcast', 1), ('hadoop', 1), ('itheima', 1), ('itcast', 1), ('hadoop', 1), ('yarn', 1), ('mapreduce', 1), ('', 1), ('', 1)]

将元组的value 按照key来分组:
 [('itcast', 4), ('hadoop', 7), ('hdfs', 2), ('yarn', 2), ('', 2), ('itheima', 4), ('mapreduce', 2)]

第五个算子: groupBy算子

功能:将rdd的数据分组
语法: rdd.groupBy(func)
func:(T) -> K 传入一个值,返回值无所谓; 返回的值就是分组的

rdd=sc.parallelize([('a',1),('a',2),('a',3),('c',1),('c',1)])
# t[0] 是按照key分组, 也可以按照value分组,   同样也可以定制分组,写方法,比如奇偶数
groupRdd=rdd.groupBy(lambda t:t[0])
groupRddList=groupRdd.map(lambda t:(t[0],list(t[1])))

print(groupRddList.collect())


[('c', [('c', 1), ('c', 1)]), ('a', [('a', 1), ('a', 2), ('a', 3)])]

留下疑问:分组之后,怎么求和/最大/最小值/平均值/计数?

第六个算子:Filter 过滤数据

功能: 过滤符合条件的数据
filter(func)
func(x) -> boolean

rdd=sc.parallelize([1,2,3,4,5,6])
rdd.filter(lambda x:x%2==1).collect()

[1, 3, 5]

第七个算子: distinct 去重

# 单值去重
rdd=sc.parallelize([1,2,1,1,2,3,3,3,2,4,16])
print(rdd.distinct().collect())

#元组也可以去重
rdd2=sc.parallelize([('a',1),('a',2),('c',1),('c',1)])
print(rdd2.distinct().collect())


[2, 4, 16, 1, 3]
[('a', 1), ('a', 2), ('c', 1)]

第八个算子: union 合并,不会去重

rdd1=sc.parallelize([1,2,1,1,2,3,3,3,2,4,16])
rdd2=sc.parallelize([100,200])

#只合并,不会去重
print(rdd1.union(rdd2).collect())
#手动调用distinct()去重
print(rdd1.union(rdd2).distinct().collect())


[1, 2, 1, 1, 2, 3, 3, 3, 2, 4, 16, 100, 200]
[4, 16, 100, 200, 1, 2, 3]

第九个算子: join 两个RDD算子内/外连接

#部门ID和员工姓名
x = sc.parallelize([(1001,"zhangsan"),(1002,"isi"),(1003,"wangwu"),(1004,"zhangliu")])
# 部门ID和部门名称
y = sc.parallelize([(1001,"销售部"),(1002,"教育部")])
# join是内连接,按照key进行关联
print(x.join(y).collect())

# 左连接
print(x.leftOuterJoin(y).collect())
# 右连接
print(x.rightOuterJoin(y).collect())



[(1001, ('zhangsan', '销售部')), (1002, ('isi', '教育部'))]
[(1004, ('zhangliu', None)), (1001, ('zhangsan', '销售部')), (1002, ('isi', '教育部')), (1003, ('wangwu', None))]
[(1001, ('zhangsan', '销售部')), (1002, ('isi', '教育部'))]

第十个算子: intersection 求两个rdd的交集

rdd1 = sc.parallelize([('a',1),('b',1),('c',1)])
rdd2 = sc.parallelize([('a',1),('c',1)])
inter_rdd=rdd1.intersection(rdd2)
print(inter_rdd.collect()) 


[('a', 1), ('c', 1)]

第十一个算子: glom 按分区给数据加上嵌套

功能:将RDD的数据加上嵌套,这个嵌套按照分区来进行,比如RDD数据[1,2,3,4,5] 有2个分区那么,被glom后,数据变成: [ [1,2,3],[4,5] ]
使用方法:
rdd .glom()

rdd=sc.parallelize([1,2,3,4,5,6,7])
print(rdd.glom().collect())

[[1, 2, 3], [4, 5, 6, 7]]

第十二个算子: groupByKey 针对KV自动按照key分组

rdd = sc.parallelize([('a',1),('a',1),('b',1),('b',1),('b',1)])
grouped_rdd = rdd.groupByKey()
print(grouped_rdd.map(lambda x: (x[0],list(x[1]))).collect())


[('b', [1, 1, 1]), ('a', [1, 1])]

第十三个算子: sortBy算子, 对rdd排序

语法: rdd.sortBy(func,ascending=False, numPartitions=1)

  • func: (T) U: 告知按照dd中的哪个数据进行排序,比如 lambda x: [1] 表按照rdd中的第二列元素进行排序
  • ascending True升序 False 降序
  • numPartitions: 用多少分区排序
rdd=sc.parallelize([9,5,6,7,1,2,3,4])
print(rdd.sortBy(lambda x:x).collect())

rdd=sc.parallelize([1,2,1,1,2,3,3,3,2,4,16])
print(rdd.sortBy(lambda x:x).collect())

rdd=sc.parallelize([('a',32),('a',21),('a',73),('c',31),('c',10)])
print(rdd.sortBy(lambda x:x[1]).collect())


[1, 2, 3, 4, 5, 6, 7, 9]
[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 16]
[('c', 10), ('a', 21), ('c', 31), ('a', 32), ('a', 73)]

第十四个算子: sortByKey算子, 对KV类型的key进行排序

rdd=sc.parallelize([('a',32),('c',31),('a',21),('a',73),('c',10)])
#默认按照key排序
print(rdd.sortByKey(ascending=False).collect())


[('c', 31), ('c', 10), ('a', 32), ('a', 21), ('a', 73)]

案列

需求:

读取data文件夹中的 order.text文件,提取北京的数据,组合北京和商品类别进行输出

数据格式

{“id”:1,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“平板电脑”,“areaName”:“北京”,“money”:“1450”}|{“id”:2,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“手机”,“areaName”:“北京”,“money”:“1450”}|{“id”:3,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“手机”,“areaName”:“北京”,“money”:“8412”}
{“id”:4,“timestamp”:“2019-05-08T05:01.00Z”,“category”:“电脑”,“areaName”:“上海”,“money”:“1513”}|{“id”:5,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“家电”,“areaName”:“北京”,“money”:“1550”}|{“id”:6,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“电脑”,“areaName”:“杭州”,“money”:“1550”}
{“id”:7,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“电脑”,“areaName”:“北京”,“money”:“5611”}|{“id”:8,“timestamp”:“2019-05-08T03:01.00Z”,“category”:“家电”,“areaName”:“北京”,“money”:“4410”}|{“id”:9,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“家具”,“areaName”:“郑州”,“money”:“1120”}
{“id”:10,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“家具”,“areaName”:“北京”,“money”:“6661”}|{“id”:11,“timestamp”:“2019-05-08T05:03.00Z”,“category”:“家具”,“areaName”:“杭州”,“money”:“1230”}|{“id”:12,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“书籍”,“areaName”:“北京”,“money”:“5550”}
{“id”:13,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“书籍”,“areaName”:“北京”,“money”:“5550”}|{“id”:14,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“电脑”,“areaName”:“北京”,“money”:“1261”}|{“id”:15,“timestamp”:“2019-05-08T03:03.00Z”,“category”:“电脑”,“areaName”:“杭州”,“money”:“6660”}
{“id”:16,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“电脑”,“areaName”:“天津”,“money”:“6660”}|{“id”:17,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“书籍”,“areaName”:“北京”,“money”:“9000”}|{“id”:18,“timestamp”:“2019-05-08T05:01.00Z”,“category”:“书籍”,“areaName”:“北京”,“money”:“1230”}
{“id”:19,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“电脑”,“areaName”:“杭州”,“money”:“5551”}|{“id”:20,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“电脑”,“areaName”:“北京”,“money”:“2450”}
{“id”:21,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“食品”,“areaName”:“北京”,“money”:“5520”}|{“id”:22,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“食品”,“areaName”:“北京”,“money”:“6650”}
{“id”:23,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“服饰”,“areaName”:“杭州”,“money”:“1240”}|{“id”:24,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“食品”,“areaName”:“天津”,“money”:“5600”}
{“id”:25,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“食品”,“areaName”:“北京”,“money”:“7801”}|{“id”:26,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“服饰”,“areaName”:“北京”,“money”:“9000”}
{“id”:27,“timestamp”:“2019-05-08T01:03.00Z”,“category”:“服饰”,“areaName”:“杭州”,“money”:“5600”}|{“id”:28,“timestamp”:“2019-05-08T01:01.00Z”,“category”:“食品”,“areaName”:“北京”,“money”:“8000”}|{“id”:29,“timestamp”:“2019-05-08T02:03.00Z”,“category”:“服饰”,“areaName”:“杭州”,“money”:“7000”}

import json

#1.读取文件
rdd = sc.textFile("/order.txt")

# 2.将每条json数据取出
json_str_rdd = rdd.flatMap(lambda x: x.split("|") )

# 3.将每个json字符串,变成字典对象
json_dict_rdd = json_str_rdd.map(lambda x: json.loads(x) )

# 4.过滤数据,只保留北京
beijing_rdd = json_dict_rdd.filter(lambda x: x['areaName']=="北京")

# 5.组合北京 和 商品类型
combine_rdd = beijing_rdd.map(lambda x: x['areaName'] + ""+ x['category'])

# 6.去重,并且输出
print(combine_rdd.distinct().collect())


['北京平板电脑', '北京家电', '北京家具', '北京书籍', '北京手机', '北京电脑', '北京食品', '北京服饰']

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值