RDD编程学习笔记2_键值对RDD_综合案例-计算每种图书的每天平均销量

常见操作

reduceByKey和groupByKey的区别

groupByKey只做分组,不会进行汇总
reduceByKey会进行汇总求和(写过map,reduce函数框架的话应该很好理解)

groupByKey可以通过利用Iterable的容器函数达到一些reduceByKey的效果
以下三种操作是等价的

########## 起始操作 #############
scala> val words = Array("One","Two","Two","Three","Three","Three")
words: Array[String] = Array(One, Two, Two, Three, Three, Three)

scala> val wordRdd = sc.parallelize(words).map(word => (word,1))
wordRdd: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[40] at map at <console>:26

########## 3种求和方式 ###########
scala> val word_add = wordRdd.reduceByKey(_+_)
word_add: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[41] at reduceByKey at <console>:28

scala> val word_wadd = wordRdd.reduceByKey((a,b)=>a+b)
word_wadd: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[42] at reduceByKey at <console>:28

scala> val word_groupadd = wordRdd.groupByKey().map(t => (t._1,t._2.sum))
word_groupadd: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[44] at map at <console>:28

########### stdout输出查看 ############
scala> word_add.foreach(println)
(Two,2)
(One,1)
(Three,3)

scala> word_wadd.foreach(println)
(Two,2)
(One,1)
(Three,3)

scala> word_groupadd.foreach(println)
(Two,2)
(One,1)
(Three,3)

其他一些操作

keys,values(这两个就是通过RDDval.keys或者RDDval.values生成新的RDD)
mapValues(见综合案例)

根据键或值排序sortByKey,sortBy

sortByKey默认按照key升序排序
sortByKey(false)则为按照key降序排序

如果要对value排序,则
RDDval.reduceByKey(_+_).sortBy(_._2,false).collect
根据值降序排序

########## 初始化 #############
scala> val rdd = sc.parallelize(Array(("spark",2),("hadoop",6),("hadoop",4),("spark",6)))
rdd: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[35] at parallelize at <console>:24

########## 操作输出 ############
scala> var ans = rdd.reduceByKey(_+_).sortBy(_._2,false).collect
ans: Array[(String, Int)] = Array((hadoop,10), (spark,8))

scala> ans.foreach(println)
(hadoop,10)
(spark,8)

join

key相同

综合案例-计算每种图书的每天平均销量

############# 输入数据 #############
scala> val rdd = sc.parallelize(Array(("spark",2),("hadoop",6),("hadoop",4),("spark",6)))
rdd: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[35] at parallelize at <console>:24

############# 处理计算(后面有详解解释) ##############
scala> rdd.mapValues(x => (x,1)).reduceByKey((x,y) => (x._1+y._1,x._2 + y._2)).mapValues(x => (x._1 / x._2)).collect()
res13: Array[(String, Int)] = Array((spark,4), (hadoop,5))

上面语句中,mapValues(x => (x,1))中出现了变量x,reduceByKey((x,y) => (x._1+y._1,x._2 + y._2))中也出现了变量x,mapValues(x => (x._1 / x._2))也出现了变量x。但是,必须要清楚,这三个地方出现的x,虽然都具有相同的变量名称x,但是,彼此之间没有任何关系,它们都处在不同的变量作用域内。如果你觉得这样会误导自己,造成理解上的掌握,实际上,你可以把三个出现x的地方分别替换成x1、x2、x3也是可以的,但是,很显然没有必要这么做。

给每次销售计算1

调用mapValues()函数,把rdd中的每个键值对(key,value)的"value部分"进行修改,把value转换成键值对(value,1),其中,数值1表示这个key在rdd中出现了1次。

分步运行的结果是这样的

scala> rdd.mapValues(x => (x,1)).collect()
res23: Array[(String, (Int, Int))] = Array((spark,(2,1)), (hadoop,(6,1)), (hadoop,(4,1)), (spark,(6,1)))

计算总销量和销售次数

然后调用reduceByKey()算出总销量和计算次数
reduceByKey(func)的功能是使用func函数合并具有相同键的"值"。这里的func函数就是Lamda表达式(x,y) => (x._1+y._1,x._2 + y._2),这个表达式中,x和y都是value,而且是具有相同key的两个键值对所对应的value

分步运行结果是这样的

扫描二维码关注公众号,回复: 9335967 查看本文章
scala> rdd.mapValues(x => (x,1)).reduceByKey((x,y) => (x._1+y._1,x._2 + y._2)).collect()
res24: Array[(String, (Int, Int))] = Array((spark,(8,2)), (hadoop,(10,2)))

求平均

再调用mapValues()函数,把rdd中的每个键值对(key,value)的"value部分"进行修改
mapValues(x => (x._1 / x._2))操作时,key不变,value中的第一个值除以第二个值

分步执行结果

scala> rdd.mapValues(x => (x,1)).reduceByKey((x,y) => (x._1+y._1,x._2 + y._2)).mapValues(x => (x._1 / x._2)).collect()
res25: Array[(String, Int)] = Array((spark,4), (hadoop,5))

参考

子雨老师的课
子雨老师实验室的教程

发布了34 篇原创文章 · 获赞 4 · 访问量 7548

猜你喜欢

转载自blog.csdn.net/neve_give_up_dan/article/details/104105386