Spark-RDD

弹性分布式数据集(Resilient Distribute Dataset)

  1. RDD其实就是分布式元素的集合。
  2. 在Spark中,对数据的所有操作不外乎创建RDD,转化已有的RDD以及调用RDD操作进行求值。
  3. Spark会自动讲RDD中的数据分发到集群上,并讲操作并行化执行。

初始化sparkcontext:

from pyspark import SparkContext , SparkConf
#创建一个conf对象来配置应用,此处设置为本地,名字为My App
conf = SparkConf().setMaster("loacal").setAppName("My App")
#基于配置的应用conf来创建一个SparkContext对象
sc = SparkContext(conf = conf)

RDD基础:

Spark中RDD就是一个不可变的分布式对象集合。每个RDD都被分为多个分区,这些分区被运行在集群中的不同节点上。


例如:

创建RDD:

lines = sc.textFile("README.md")

创建出来后,RDD支持两种类型的操作:转化操作(transformation)和行动操作(action)。转化操作会由一个RDD生成一个新的RDD。


调用转化操作:

pythonlines = lines.filter(lamda line : "Python" in line)

行动操作:

lines.first()

转化操作和行动操作的区别在于Spark计算RDD的方式不同。


python进行union转化操作:

lines = sc.textFile("README.md")
PythonRDD = lines.filter(lambda x : "Python" in x)
ScalaRDD = lines.filter(lambda x : "Scala" in x)
languageRDD = PythonRDD.union(ScalaRDD)

RDD 的转化操作都是惰性求值的,也就是说在被调用行动操作之前,spark不会进行计算。所以我们不应该把RDD看作是存放着特定数据的数据集,而最好把每个RDD看作我们通过转化操作侯建出来的。因此当我们调用sc.textFile()时,数据并没有被读取进来,而是在必要时才会读取。


传递函数:

PythonRDD = lines.filter(lambda x : "Python" in x)
#可以等价与:
def containsPython(s):
	return "Python" in s
P_RDD = lines.filter(containsPython)

需要注意的一点是,当你传递的对象是某个对象的成员时,或者某个对象的一个字段的引用(如self.filed),spark会讲整个对象发到工作节点上。
传递带字段的函数(错误行为):

class AA():
	def __init__(self,query):
		self.query = query
	def getinfo():
		return rdd.filter(lambda x : self.query in x)

不传递带字段的函数(正确行为):

class AA():
	...
	def getinfo():
	query = self.query
		return rdd.filter(lambda x : query in x)

常见的转化操作(产生新的RDD)和行动操作

常见的转化操作

  1. map() 。map()接受一个函数,把这个函数用于RDD中的每一个元素,将函数返回结果作为结果RDD中对应的元素值。
  2. filter(). filter()接受一个函数,并将RDD中满足这个函数(通常来说就是这个函数返回True)的元素放入新的RDD中。

例:用转化操作map()对RDD中的所有元素求平方,返回一个新的RDD

nums = sc.parallelize([1,2,3,4]) #建立rdd
squared_rdd = nums.map(lambda x : x*x) #转化rdd
squared_rdd = squared_rdd.collect() #把rdd转化为列表
squared_rdd
[1, 4, 9, 16]

flatMap()与map()类似,只是这个转化可以由1个元素返回多个元素。比如把英文句子切分成单词。
例:用转化操作flatMap()将行数据切分为单词:

lines = sc.parallelize(["hello world","hi"])
words = lines.flatMap(lambda line : line.split(" "))
words.first()
'hello'


对数据为{1,2,3,3}的RDD进行进行基本的RDD转化操作:num = sc.parallelize([1,2,3,3])

函数名目的示例结果
map()将RDD中每个元素都输入函数中得到返回的元素构成新的RDDrdd_map = num.map(lambda x : x+1)[2, 3, 4, 4]
flatMap()将RDD中每个元素都输入函数中得到返回的多个元素构成新的RDDrdd_flatMap = num.flatMap(lambda x : range(x,4))[1, 2, 3, 2, 3, 3, 3]
filter把原元素输入传入的函数中返回返回值为True的原元素组成的新rddfilter_rdd = num.filter(lambda x : x != 2)[1, 3, 3]
distinct()去重distinct_rdd = num.distinct()[1, 2, 3]
sample()采样sample_rdd = num.sample(False,0.5)[1, 2]

对数据分别为{1,2,3}和{3,4,5}的RDD进行针对两个RDD的转化操作num1 = sc.parallelize([1,2,3])num2 = sc.parallelize([3,4,5])

函数名目的示例结果
union()生成一个包含两个RDD中所有元素的RDDunion_rdd = num1.union(num2)[1, 2, 3, 3, 4, 5]
intersection()求两个RDD共同元素的RDDintersection_rdd = num1.intersection(num2)[3]
subtract()移除一个RDD中存在与另一个RDD中的元素(不改变原来的RDD,而是生产一个新的RDD)subtract_rdd = num1.subtract(num2)[1, 2]
cartesian()与另一个RDD的笛卡尔积cartesian_rdd = num1.cartesian(num2)[(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]

常见的行动操作(不产生新的RDD,返回数值或数值集合)

例如对元素进行累加:

num1 = sc.parallelize([1,2,3])
sum = num1.reduce(lambda x,y:x+y)
print(sum)
6

对一个数据为{1,2,3,3}的RDD进行基本的RDD行动操作:num = sc.parallelize([1,2,3,3])

函数名目的示例结果
collect()返回RDD中所有的元素num.collect()[1, 2, 3, 3]
count()RDD中元素的个数num.count()
countByValue()各元素在RDD中出现的次数,在python中返回的是一个字典dic = num.countByValue()defaultdict(<class ‘int’>, {1: 1, 2: 1, 3: 2})
take(n)返回RDD中n个元素,python中返回列表num.take(2)[1, 2]
top(n)返回RDD中最前面的n个元素num.top(2)[3, 3]
takeOrdered(n)(ordering)在RDD中按照提供的顺序返回最前面的n个元素num.takeOrdered(2)[1, 2]
takeSample()从RDD中返回任意一些元素num.takeSample(False,1)随机值如[1]
reduce(func)并行整合RDD中所有数据num.reduce(lambda x,y : x*y)18
fold(zero)(func)和reduce一样,但是需要提供初始值num.fold(0, lambda x,y : x+y)9
aggregate((zeroValue),(seqOp,comOp))和reduce相似,但是通常返回不同的类型sumcount = num.aggregate((0,0,), (lambda acc,value:(acc[0]+value , acc[1]+1)),(lambda acc1,acc2 : (acc1[0]+acc2[0],acc1[1]+acc2[1])))(9, 4)
foreach(func)

持久化操作

Spark RDD是惰性求值的,如果会多次使用同一个RDD,为避免重复计算,.可以将其持久化.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值