键值对 RDD 的创建
from pyspark import SparkConf ,SparkContext
conf = SparkConf().setMaster("local").setAppName("RDDKeyAndValue")
sc = SparkContext(conf= conf)
第一种创建方式:从文件中加载
可以采用多种方式创建键值对 RDD ,其中一种主要方式是使用 map() 函数来实现
# 第一种创建方式:从文件中加载
# 可以采用多种方式创建键值对 RDD ,其中一种主要方式是使用 map() 函数来实现
lines = sc.textFile("file:///home/hadoop/MyTmp/sparkwordcount.txt")
pairRDD = lines.flatMap(lambda line:line.split(" ")).map(lambda word:(word,1))
pairRDD.foreach(print)
运行结果:
# 第二种创建方式:通过并行集合(列表)创建 RDD
# 第二种创建方式:通过并行集合(列表)创建 RDD
list = ["hadoop","spark","Hive","spark"]
rdd = sc.parallelize(list)
pairRDD = rdd.map(lambda word:(word,1))
pairRDD.foreach(print)
运行结果:
常用的键值对 RDD 转换操作
函数名 | 目的 |
---|---|
reduceByKey(func) | 合并具有相同键的值 |
groupByKey() | 对具有相同键的值进行分组 |
combineByKey(createCombine,mergeValue,mergeCombiners,partitioner) | 使用不同的返回类型合并具有相同键的值 |
mapValues(func) | 对pairRDD 中的每个值应用一个函数而不改变键 |
flatMapValues(func) | 对pairRDD中的每个值应用一个返回迭代器的函数,然后对返回的每个元素都生成一个对应原键的键值对记录,通常用于符号化 |
keys() | 返回一个仅包含键的RDD |
alues() | 返回一个仅包含值的RDD |
sortByKey() | 返回一个根据键排序的RDD |
reduceByKey(func) 使用func函数合并具有相同键的值
# reduceByKey(func) Demo
pairRDD = sc.parallelize([("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)])
pairRDD.reduceByKey(lambda a,b:a+b)
pairRDD.foreach(print)
运行结果如下:
**groupByKey()**对具有相同键的值进行分组
list = [("spark",1),("spark",2),("hadoop",3),("hadoop",4)]
pairRDD = sc.parallelize(list)
print("result1:",pairRDD.groupByKey())
print("*"*30)
pairRDD.groupByKey().foreach(print)
运行结果如下:
reduceByKey 和 groupByKey 的区别
- reduceByKey 用于对每个 key 对应的多个 value 进行merge 操作,最重要的是它能够在本地先进行 merge
操作,并且 merge 操作可以通过函数自定义 - groupByKey 也是对每个 key 进行操作,但只生成一个sequence , groupByKey 本身不能自定义函数,需要先用
groupByKey 生成 RDD ,然后才能对此 RDD 通过map 进行自定义函数操作
keys 只会把 Pair RDD 中的 key 返回形成一个新的 RDD
# keys 只会把 Pair RDD 中的 key 返回形成一个新的 RDD
list = [("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
pairRDD = sc.parallelize(list)
pairRDD.keys().foreach(print)
运行结果:
values 只会把 Pair RDD 中的 value 返回形成一个新的 RDD
# values 只会把 Pair RDD 中的 value 返回形成一个新的 RDD 。
list = [("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
pairRDD = sc.parallelize(list)
pairRDD.values().foreach(print)
运行结果:
sortByKey() 的功能是返回一个根据键排序的 RDD
# sortByKey() 的功能是返回一个根据键排序的 RDD
list = [("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
pairRDD = sc.parallelize(list)
pairRDD.foreach(print)
print("*"*20)
pairRDD.sortByKey().foreach(print)
运行结果如下:
mapValues(func) 对键值对 RDD 中的每个 value 都应用一个函数,但是, key 不会发生变化
# mapValues(func)
# 对键值对 RDD 中的每个 value 都应用一个函数,但是, key 不会发生变化
list = [("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
pairRDD = sc.parallelize(list)
pairRDD1 = pairRDD.mapValues(lambda x:x+1)
pairRDD1.foreach(print)
运行结果如下:
针对两个pairRDD 的转化操作
rdd={(1,2),(3,4),(3,6)} otherRDD ={(3,9)}
函数名 | 目的 | 示例 | 结果 |
---|---|---|---|
subtractByKey() | 删掉rdd中键与ohterRDD 中的键相同的元素 | rdd.subtractByKey(otherRDD) | {(1,2)} |
join | 对两个RDD 进行内连接 | rdd.join(otherRDD) | {3,(4,9),(3,(6,9))} |
**subtractByKey() 删掉rdd中键与ohterRDD 中的键相同的元素 **
pairRDD1 = sc.parallelize([("spark",1),("spark",2),("hadoop",3),("hadoop",5)])
pairRDD2 = sc.parallelize([("spark","fast")])
pairRDD3 = pairRDD1.subtractByKey(pairRDD2)
pairRDD3.foreach(print)
结果如下:
join 就表示内连接。对于内连接,对于给定的两个输入数据集 (K,V1) 和 (K,V2) ,只有在两个数据集中都存在的 key 才会被输出,最终得到一个 (K,(V1,V2)) 类型的数据集
# join
# join 就表示内连接。对于内连接,对于给定的两个输入数据集 (K,V1) 和 (K,V2) ,只有在两个数据集中都存在的 key 才会被输出,最终得到一个 (K,(V1,V2)) 类型的数据集
pairRDD1 = sc.parallelize([("spark",1),("spark",2),("hadoop",3),("hadoop",5)])
pairRDD2 = sc.parallelize([("spark","fast")])
pairRDD3 = pairRDD1.join(pairRDD2)
pairRDD3.foreach(print)
结果如下:
一个综合实例
题目:给定一组键值对 (“spark”,2),(“hadoop”,6),(“hadoop”,4),(“spark”,6) ,键值对的 key 表示图书名称, value 表示某天图书销量,请计算每个键对应的平均值,也就是计算每种图书的每天平均销量。
rdd = sc.parallelize([("spark",2),("hadoop",6),("hadoop",4),("spark",6)])
rddResult = rdd.mapValues(lambda x:(x,1)).\
reduceByKey(lambda x,y:(x[0]+y[0],x[1]+y[1])).\
mapValues(lambda x:x[0]/x[1])
print(rddResult.collect())
运行结果下: