RDD 分组 TOP n

##原始数据

香菜		2.80	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
大葱		2.80	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
葱头		1.60	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
大蒜		3.60	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
蒜苔		6.20	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
韭菜		5.60	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
青椒		5.20	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
茄子		5.40	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
西红柿	4.80	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳
黄瓜		3.40	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西	汾阳

加载数据

val product=sc.textFile("file:///root/text/text/products.txt")
product.take(1)
res0: Array[String] = Array(香菜		2.80	2018/1/1	山西汾阳市晋阳农副产品批发市场	山西汾阳)

数据清洗

出去一条数据不是六列的和重复的数据

val temp=product.distinct.filter(_.split("\t").length==6)

代码

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)})
.reduceByKey(_+_)
.map({case((province,market),nums)=>(province,(market,nums))})
.groupByKey().mapValues(x=>x.toList.sortBy(_._2)(Ordering.Int.reverse).take(3))
.foreach(println)

对每个省内的市场蔬菜给 1

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)}).take(3)
res9: Array[((String, String), Int)] = Array(
((内蒙古,呼和浩特市东瓦窑批发市场),1), 
((北京,北京八里桥农产品中心批发市场),1), 
((广西,广西柳州柳邕农副产品批发市场),1))

把每个省的市场的菜品统计

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)}).reduceByKey((x,y)=>x+y).take(3)
res10: Array[((String, String), Int)] = Array(
((江苏,江苏建湖县水产批发市场),8), 
((江苏,江苏宜兴蔬菜副食品批发市场),32), 
((陕西,陕西泾阳县云阳蔬菜批发市场),25))

使用模式匹配进行类型转换

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)})
.reduceByKey((x,y)=>x+y)
.map({case ((province,market),nums)=>(province,(market,nums))}).take(3)
res11: Array[(String, (String, Int))] = Array(
(江苏,(江苏建湖县水产批发市场,8)), 
(江苏,(江苏宜兴蔬菜副食品批发市场,32)), 
(陕西,(陕西泾阳县云阳蔬菜批发市场,25)))

将各个市场归到所在省

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)})
.reduceByKey((x,y)=>x+y)
.map({case ((province,market),nums)=>(province,(market,nums))})
.groupByKey().take(3)
res15: Array[(String, Iterable[(String, Int)])] = Array(
(辽宁,CompactBuffer((辽宁朝阳市果菜批发市场,37), (辽宁阜新市瑞轩蔬菜农副产品综合批发市场,53), (大连水产品交易市场有限公司,42), (辽宁鞍山宁远农产品批发市场,46), (大连双兴批发市场,31))), 
(浙江,CompactBuffer((浙江嘉兴蔬菜批发交易市场,51), (浙江义乌农贸城,40), (浙江嘉善浙北果蔬菜批发交易,35))), 
(内蒙古,CompactBuffer((呼和浩特市东瓦窑批发市场,85), (内蒙呼市食全食美股份有限公司石羊桥交易中,27), (内蒙包头市场友谊蔬菜批发市场,55))))

对各个的省市场按菜品数降序排列取前三进行

temp.map(line=>{val x=line.split("\t");((x(4),x(3)),1)})
.reduceByKey(_+_)
.map({case((province,market),nums)=>(province,(market,nums))})
.groupByKey().mapValues(x=>x.toList.sortBy(_._2)(Ordering.Int.reverse).take(3))
.take(3).foreach(println)
(辽宁,List((辽宁阜新市瑞轩蔬菜农副产品综合批发市场,53), (辽宁鞍山宁远农产品批发市场,46), (大连水产品交易市场有限公司,42)))
(浙江,List((浙江嘉兴蔬菜批发交易市场,51), (浙江义乌农贸城,40), (浙江嘉善浙北果蔬菜批发交易,35)))
(内蒙古,List((呼和浩特市东瓦窑批发市场,85), (内蒙包头市场友谊蔬菜批发市场,55), (内蒙呼市食全食美股份有限公司石羊桥交易中,27)))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark RDD分组取TopN案例是指在一个RDD中,根据某个键值进行分组,然后对每个组内的数据进行排序,取出每个组内的N个数据。这种操作在数据分析和处理中非常常见,可以用于统计每个地区的销售额排名N的产品、每个用户的消费排名N的商品等。 优化方面,可以考虑使用Spark SQL或DataFrame来实现分组取TopN操作,因为它们提供了更高级的API和优化技术,可以更快速地处理大规模数据。另外,可以使用分布式缓存技术将数据缓存到内存中,以加快数据访问速度。还可以使用分区和并行计算等技术来提高计算效率。 ### 回答2: Spark RDD分组取Top N的案例可以是对一个大数据集中的用户数据进行分组,然后取每个组中消费金额最高的N个用户。这个案例可以通过以下步骤来实现: 1. 将用户数据载入Spark RDD中,每个数据记录包含用户ID和消费金额。 2. 使用groupBy函数将RDD按照用户ID进行分组,得到一个以用户ID为key,包含相同用户ID的数据记录的value的RDD。 3. 对每个分组的value调用top函数,指定N的值,以获取每个分组中消费金额最高的N个用户。 4. 可以将每个分组中Top N的用户使用flatMap函数展开为多个记录,并可以添加一个新的字段表示该记录属于哪个分组。 5. 最后,可以使用collect函数将结果转化为数组或者保存到文件或数据库中。 在这个案例中,进行优化的关键是减少数据的传输和处理开销。可以使用缓存或持久化函数对RDD进行优化,以减少重复计算。另外,可以使用并行操作来加速计算,如使用并行的排序算法,或向集群中的多个节点分发计算任务。 对于分组取Top N的优化,还可以考虑使用局部聚合和全局聚合的策略。首先对每个分组内的数据进行局部聚合,例如计算每个分组M个最大值。然后,对所有分组的局部聚合结果进行全局聚合,例如计算所有分组K个最大值。 另一个优化策略是使用采样技术,例如随机采样或分层采样,以减少需要处理的数据量。 最后,还可以考虑使用Spark的其他高级功能,如Broadcast变量共享数据,使用累加器进行计数或统计等,来进一步提高性能和效率。 ### 回答3: Spark RDDSpark 提供的一种基于内存的分布式数据处理模型,其核心数据结构是弹性分布式数据集(RDD)。 在 Spark RDD 中,分组取TopN 是一种常见的需求,即对 RDD 中的数据按某个字段进行分组,并取出每个分组中字段值最大的 N 个数据。 下面以一个示例来说明分组取 TopN 的用法和优化方法: 假设有一个包含学生信息的 RDD,其中每条数据都包括学生的学科和分数,我们希望对每个学科取出分数最高的 3 名学生。 ```python # 创建示例数据 data = [ ("语文", 80), ("数学", 90), ("语文", 85), ("数学", 95), ("语文", 75), ("数学", 92), ("英语", 88) ] rdd = sc.parallelize(data) # 分组取TopN top3 = rdd.groupByKey().mapValues(lambda x: sorted(x, reverse=True)[:3]) # 输出结果 for subject, scores in top3.collect(): print(subject, scores) # 输出结果: # 数学 [95, 92, 90] # 语文 [85, 80, 75] # 英语 [88] ``` 在上述代码中,我们先使用 `groupByKey()` 对 RDD 进行分组操作,然后使用 `mapValues()` 对每个分组内的数据进行排序并取 3 个值。 这种方式的优化点在于,通过将分组操作和取 TopN 操作分开,可以减轻数据倾斜的问题。同时,对每个分组进行排序会占用大量计算资源,可以考虑将数据转换为 Pair RDD,并利用 Spark 提供的 `top()` 算子来优化取 TopN 的操作。 ```python # 转换为 Pair RDD pair_rdd = rdd.map(lambda x: (x[0], x[1])) # 分组并取TopN,使用top()算子代替排序操作 top3 = pair_rdd.groupByKey().mapValues(lambda x: sorted(x, reverse=True)).mapValues(lambda x: x[:3]) # 输出结果 for subject, scores in top3.collect(): print(subject, scores) # 输出结果: # 数学 [95, 92, 90] # 语文 [85, 80, 75] # 英语 [88] ``` 通过以上优化,我们可以更好地处理大规模数据集下的分组取 TopN 的需求,提高计算性能和资源利用率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值