Spark基础

1. 创建程序的执行入口SparkContext对象

1.在pycharm中创建
from pyspark import SparkContext,SparkConf
if __name__=='__main':
    conf=SparkConf().setAppName("hello").setMaster("local[*]")
    sc=SparkContext(conf=conf)
2.在jupyter中创建
import findspark
findspark.init()
import pyspark
from pyspark import SparkContext
sc=SparkContext("local","app")

2.RDD算子

rdd算子分为两大类,Transformation算子与Action算子
区别:
Transformation算子返回值仍然是RDD,只是将RDD经过了转换;
Action算子的返回值不是RDD
Transformation相当于在构建计划,action是一个指令,让这个计划开始工作。没有Action算子,Transformation算子就不工作

(1)Transformation算子

  • map算子

参数为函数,返回值是RDD

rdd=sc.parallelize([1,2,3,4,5,6],3)
def add(data):
    return data*10
rdd.map(add).collect()
#方法二:使用lambda编写匿名函数
rdd.map(lambda data:data*10).collect()

[10, 20, 30, 40, 50, 60]

3个分区都作用了map函数,并将分区的每个元素都调用add函数,乘以10。最终汇总各分区结果仍返回RDD

  • flatMap算子

先对RDD执行map,然后解除嵌套

rdd1=sc.parallelize(["hadoop spark hadoop","spark hadoop hadoop","hadoop flink spark"])
#使用map
rdd1.map(lambda s:s.split(" ")).collect()

[['hadoop', 'spark', 'hadoop'],
 ['spark', 'hadoop', 'hadoop'],
 ['hadoop', 'flink', 'spark']]

#使用flatMap
rdd1.flatMap(lambda s:s.split(" ")).collect()

['hadoop',
 'spark',
 'hadoop',
 'spark',
 'hadoop',
 'hadoop',
 'hadoop',
 'flink',
 'spark']
  • reduceByKey算子

针对k,v型数据,自动按照key分组,然后将组内value聚合

rdd3=sc.parallelize([('a',1),('a',1),('b',1),('b',1),('b',1)])
rdd3.reduceByKey(lambda a,b:a+b).collect()

[('a', 2), ('b', 3)]

叠加式相加:对于’a’:1+1=2, 对于‘b’:1+1=2,2+1=3

  • mapValues算子

传入RDD,但只对values进行操作,注意与map的区别

rdd4=sc.parallelize([('a',1),('a',11),('b',5),('b',6),('b',1)])
rdd4.mapValues(lambda x:x*10).collect()

[('a', 10), ('a', 110), ('b', 50), ('b', 60), ('b', 10)]
  • groupBy算子

作用:对数据进行分组
传入的函数的意思是,通过这个函数,确认通过什么分组

rdd5=sc.parallelize([('a',1),('a',1),('b',1),('b',1),('b',1)])
rdd5.groupBy(lambda t:t[0]).collect()

[('a', <pyspark.resultiterable.ResultIterable at 0x1dcaed71b48>),
 ('b', <pyspark.resultiterable.ResultIterable at 0x1dcaecd6d48>)]
 
#将可迭代的values放入列表中
rdd6.map(lambda t:(t[0],list(t[1]))).collect()

[('a', [('a', 1), ('a', 1)]), ('b', [('b', 1), ('b', 1), ('b', 1)])]
  • filter算子

作用:过滤想要的数据,逻辑值为True的保留

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

[1, 3, 5, 7]
  • distinct算子

作用:对数据去重

rdd8=sc.parallelize([1,2,1,3,4,7,7,9,8,8,3])
rdd8.distinct().collect()

[1, 2, 3, 4, 7, 9, 8]
  • union算子

将两个RDD合并成一个RDD返回,不去重

rdd9=sc.parallelize([1,2,3])
rdd10=sc.parallelize(['a',1,'b','m'])
union_rdd=rdd9.union(rdd10)
union_rdd.collect()

[1, 2, 3, 'a', 1, 'b', 'm']
  • join算子
    作用:对两个RDD进行连接操作,类似SQL语句
#部门ID和员工姓名
x=sc.parallelize([(1001,"zhangsan"),(1002,"lisi"),(1003,"wangwu")])
#部门ID和部门名称
y=sc.parallelize([(1001,"sales"),(1002,"tech")])
#join内连接
x.join(y).collect()

[(1002, ('lisi', 'tech')), (1001, ('zhangsan', 'sales'))]

#左外连接
x.leftOuterJoin(y).collect()
[(1002, ('lisi', 'tech')),
 (1001, ('zhangsan', 'sales')),
 (1003, ('wangwu', None))]
  • intersection算子

作用:计算两个RDD的交集,返回一个新的RDD

r1=sc.parallelize([('a',1),('b',1)])
r2=sc.parallelize([('a',1),('c',1)])
uni_rdd=r1.intersection(r2)
uni_rdd.collect()

[('a', 1)]
  • glom算子

作用:将RDD的数据加上嵌套,这个嵌套是根据分组进行的

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

[[1, 2], [3, 4], [5, 6]]
  • groupByKey算子

针对k,v型数据,自动按照key分组

rdd13=sc.parallelize([('a',1),('a',11),('b',5),('b',6),('b',1)])
group_rdd=rdd13.groupByKey()
group_rdd.map(lambda x:(x[0],list(x[1]))).collect()

[('a', [1, 11]), ('b', [5, 6, 1])]
  • sortBy算子

基于自己指定的排序方法,对RDD数据进行排序
注意只能确保分区内有序,分区间不一定有序

rdd14=sc.parallelize([('c',1),('f',1),('a',11),('b',3),('e',5),('k',7)])
#参数一:表示按照哪个列排序
#参数二:True表示升序,False表示降序
#参数三:排序的分区数
rdd14.sortBy(lambda x:x[1],ascending=True,numPartitions=3).collect()
[('c', 1), ('f', 1), ('b', 3), ('e', 5), ('k', 7), ('a', 11)]

rdd14.sortBy(lambda x:x[0],ascending=False,numPartitions=3).collect()
[('k', 7), ('f', 1), ('e', 5), ('c', 1), ('b', 3), ('a', 11)]
  • sortByKey算子

针对k,v型数据,按照key进行排序

rdd15=sc.parallelize([('c',1),('f',1),('a',11),('b',3),('e',5),('k',7),
                     ('y',1),('u',4),('m',1),('o',1)])
rdd15.sortByKey(ascending=True,numPartitions=1,keyfunc=lambda key:str(key).lower()).collect()

[('a', 11),
 ('b', 3),
 ('c', 1),
 ('e', 5),
 ('f', 1),
 ('k', 7),
 ('m', 1),
 ('o', 1),
 ('u', 4),
 ('y', 1)]

(2)Action算子

  • countByKey算子

统计key出现的次数

#统计单词出现的次数
rdd16=sc.parallelize("word.txt")
rdd17=rdd16.faltMap(lambda x:x.split(" ")).map(lambda x:(x,1))
res=rdd17.countByKey()
print(res)
  • collect算子

将RDD各个分区的数据统一收集到Driver中,形成一个list对象

rdd.collect()
  • reduce算子

对values进行叠加式聚合,返回值不是RDD

rdd16=sc.parallelize([1,2,3,4,5])
print(rdd.reduce(lambda a,b:a+b))

21
  • flod算子

和reduce一样,接收传入逻辑进行聚合,聚合是带有初始值的
初始值在分区内与分区间聚合时都要加上

rdd17=sc.parallelize(range(1,10),3)
print(rdd.fold(10,lambda a,b:a+b))

85
  • first算子

取出RDD的第一个元素

sc.parallelize([3,2,1]).first()

3
  • take算子

取出RDD的前n个元素

sc.parallelize([3,2,1,5,8,9]).take(5)

[3, 2, 1, 5, 8]
  • top算子

对RDD数据集降序排序,取出前n个

sc.parallelize([3,4,1,5,8,9]).top(3)

[9, 8, 5]
  • count算子

计算RDD有多少条数据

sc.parallelize([3,4,1,5,8,9]).count()

6
  • takeSample算子

随机抽取RDD数据

#参数1:True表示取同一个位置数据,False表示不允许取同一个数据
#参数2:抽样要几个
#参数3:随机数种子,若设定,每次取出的随机数据一样
rdd18=sc.parallelize([1,3,5,6,4,3,7,8,2,1])
print(rdd18.takeSample(False,5,22))

[3, 7, 1, 8, 3]
  • takeOrdered算子

对RDD进行排序(可正向可逆向)取出前n个

rdd19=sc.parallelize([1,3,5,6,4,3,7,8,2,1],1)
print(rdd19.takeOrdered(3))
[1, 1, 2]

#倒序
print(rdd19.takeOrdered(3,lambda x:-x))
[8, 7, 6]
  • foreach算子

对每一个元素,执行指定的逻辑,类似map,但没有返回值

rdd20=sc.parallelize([3,4,1,5,8,9],1)
res1=rdd.foreach(lambda x:print(x*10))
  • saveAsTextFile算子
    将RDD数据写入本地文件系统或HDFS中,有多少分区生成多少文件
rdd.savaAsTextFile("hdfs://node1:8020/output")

广播变量

把list对象传给每个分区使用时,同一个executer只用传送一个,避免资源浪费,占用网络带宽

stu_info_list=[(1,"张洁",11),
              (2,"刘培",13),
              (3,"张燕",11),
              (4,"王薇",11)]
#将本地list对象标记为广播变量
broadcast=sc.broadcast(stu_info_list)
score_info_rdd=sc.parallelize([
    (1,'语文',99),
    (2,'数学',99),
    (3,'英语',99),
    (4,'编程',99),
    (1,'语文',99),
    (2,'编程',99),
    (3,'语文',99),
    (4,'英语',99),
    (1,'语文',99),
    (3,'英语',99),
    (2,'编程',99),
])
def map_func(data):
    id=data[0]
    name=""
    #for i in stu_info_list:
    for i in broadcast.value:
        if id==i[0]:
            name=i[1]
    return (name,data[1],data[2])
print(score_info_rdd.map(map_func).collect())

[('张洁', '语文', 99), ('刘培', '数学', 99), ('张燕', '英语', 99), ('王薇', '编程', 99), ('张洁', '语文', 99), ('刘培', '编程', 99), ('张燕', '语文', 99), ('王薇', '英语', 99), ('张洁', '语文', 99), ('张燕', '英语', 99), ('刘培', '编程', 99)]

累加器

rdd=sc.parallelize([1,2,3,4,5,6,7,8,9,10],2)
count=0
def map_func(data):
    global count
    count +=1
    print(count)
rdd.map(map_func).collect()
print(count)

0
#最后的count值为0,各个分区虽然累加了,但最后没有汇总给Driver

#使用累加器
acmlt=sc.accumulator(0)
def map_func(data):
    global acmlt
    acmlt +=1
    print(acmlt)
rdd.map(map_func).collect()
print(acmlt)

10
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值