pyspark_RDD练习

本文通过 PySpark 进行一系列数据处理实战,包括计算平均数、众数、TopN、排序及连接操作。展示了如何使用 reduce, sortBy, groupByKey, join 等关键算子进行数据操作,例如求平均数、众数、查找 TopN 分数的学生、排序并返回序号、二次排序以及连接班级和成绩数据以找出平均分高于75的班级。此外,还展示了如何处理分组后的众数问题。

熟悉一些算子的常规用法,多加练习

求平均数
#任务:求data的平均值
data = [1,5,7,10,23,20,6,5,10,7,10]

rdd_data = sc.parallelize(data)
s = rdd_data.reduce(lambda x,y:x+y+0.0)
n = rdd_data.count()
avg = s/n
print("average:",avg)

average: 9.454545454545455


求众数
#任务:求data中出现次数最多的数,若有多个,求这些数的平均值
data =  [1,5,7,10,23,20,7,5,10,7,10]

rdd_data = sc.parallelize(data)
rdd_count = rdd_data.map(lambda x:(x,1)).reduceByKey(lambda x,y:x+y)
max_count = rdd_count.map(lambda x:x[1]).reduce(lambda x,y: x if x>=y else y)
rdd_mode = rdd_count.filter(lambda x:x[1]==max_count).map(lambda x:x[0])
mode = rdd_mode.reduce(lambda x,y:x+y+0.0)/rdd_mode.count()
print("mode:",mode)
mode: 8.5

求TopN
#任务:有一批学生信息表格,包括name,age,score, 找出score排名前3的学生, score相同可以任取
students = [("LiLei",18,87),("HanMeiMei",16,77),("DaChui",16,66),("Jim",18,77),("RuHua",18,50)]
n = 3

rdd_students = sc.parallelize(students)
rdd_sorted = rdd_students.sortBy(lambda x:x[2],ascending = False)

students_topn = rdd_sorted.take(n)
print(students_topn)
[('LiLei', 18, 87), ('HanMeiMei', 16, 77), ('Jim', 18, 77)]

排序并返回序号
#任务:按从小到大排序并返回序号, 大小相同的序号可以不同
data = [1,7,8,5,3,18,34,9,0,12,8]

rdd_data = sc.parallelize(data)
rdd_sorted = rdd_data.map(lambda x:(x,1)).sortByKey().map(lambda x:x[0])
rdd_sorted_index = rdd_sorted.zipWithIndex()

print(rdd_sorted_index.collect())

[(0, 0), (1, 1), (3, 2), (5, 3), (7, 4), (8, 5), (8, 6), (9, 7), (12, 8), (18, 9), (34, 10)]

二次排序
#任务:有一批学生信息表格,包括name,age,score
#首先根据学生的score从大到小排序,如果score相同,根据age从大到小

students = [("LiLei",18,87),("HanMeiMei",16,77),("DaChui",16,66),("Jim",18,77),("RuHua",18,50)]
rdd_students = sc.parallelize(students)
%%writefile student.py
#为了在RDD中使用自定义类,需要将类的创建代码其写入到一个文件中,否则会有序列化错误
class Student:
    def __init__(self,name,age,score):
        self.name = name
        self.age = age
        self.score = score
    def __gt__(self,other):
        if self.score > other.score:
            return True
        elif self.score==other.score and self.age>other.age:
            return True
        else:
            return False
from student import Student

rdd_sorted = rdd_students \
    .map(lambda t:Student(t[0],t[1],t[2]))\
    .sortBy(lambda x:x,ascending = False)\
    .map(lambda student:(student.name,student.age,student.score))

#参考方案:此处巧妙地对score和age进行编码来表达其排序优先级关系,除非age超过100000,以下逻辑无错误。
#rdd_sorted = rdd_students.sortBy(lambda x:100000*x[2]+x[1],ascending=False)

rdd_sorted.collect()
[('LiLei', 18, 87),
 ('Jim', 18, 77),
 ('HanMeiMei', 16, 77),
 ('DaChui', 16, 66),
 ('RuHua', 18, 50)]

连接操作
#任务:已知班级信息表和成绩表,找出班级平均分在75分以上的班级
#班级信息表包括class,name,成绩表包括name,score

classes = [("class1","LiLei"), ("class1","HanMeiMei"),("class2","DaChui"),("class2","RuHua")]
scores = [("LiLei",76),("HanMeiMei",80),("DaChui",70),("RuHua",60)]

rdd_classes = sc.parallelize(classes).map(lambda x:(x[1],x[0]))
rdd_scores = sc.parallelize(scores)
rdd_join = rdd_scores.join(rdd_classes).map(lambda t:(t[1][1],t[1][0]))

def average(iterator):
    data = list(iterator)
    s = 0.0
    for x in data:
        s = s + x
    return s/len(data)

rdd_result = rdd_join.groupByKey().map(lambda t:(t[0],average(t[1]))).filter(lambda t:t[1]>75)
print(rdd_result.collect())
[('class1', 78.0)]
        
分组求众数
#任务:有一批学生信息表格,包括class和age。求每个班级学生年龄的众数。

students = [("class1",15),("class1",15),("class2",16),("class2",16),("class1",17),("class2",19)]

def mode(arr):
    dict_cnt = {}
    for x in arr:
        dict_cnt[x] = dict_cnt.get(x,0)+1
    max_cnt = max(dict_cnt.values())
    most_values = [k for k,v in dict_cnt.items() if v==max_cnt]
    s = 0.0
    for x in most_values:
        s = s + x
    return s/len(most_values)

rdd_students = sc.parallelize(students)
rdd_classes = rdd_students.aggregateByKey([],lambda arr,x:arr+[x],lambda arr1,arr2:arr1+arr2)
rdd_mode = rdd_classes.map(lambda t:(t[0],mode(t[1])))

print(rdd_mode.collect())

[('class1', 15.0), ('class2', 16.0)]
### 关于头歌平台 PySpark RDD 编程教程与示例 #### 1. 头歌平台上的 Spark RDD 初级实践 头歌平台提供了丰富的 Spark RDD 编程练习资源,旨在帮助开发者掌握基本的 RDD 操作技能。通过完成指定的任务,可以逐步熟悉如何利用 PySpark 进行分布式数据处理[^3]。 以下是基于头歌平台任务的一些核心知识点总结: - **任务描述**: 平台中的典型任务包括但不限于以下几种: - 数据去重操作:通过对原始数据集进行过滤和转换,去除重复项。 - 整合排序功能:将多个数据源合并后按特定规则排序。 - 计算平均值:针对数值型数据集合执行聚合运算以得出统计结果。 这些任务的设计目的是引导用户深入理解 RDD 的工作流程及其在实际场景下的应用方式。 #### 2. PySpark RDD 基础概念回顾 为了更好地参与上述任务,在正式编码之前需先复习一下 PySpark 中有关 RDD 的基础知识。PySpark 是 Apache Spark 提供的一个 Python API 接口,允许开发人员使用熟悉的 Python 脚本来构建强大的大数据分析解决方案[^2]。 ##### (a) RDD 定义及特点 RDD(Resilient Distributed Dataset),即弹性分布式数据集,是 Spark 核心抽象之一。它具有以下几个显著特征[^4]: - 可被划分为若干个逻辑分区; - 支持对每个分区内元素逐一施加变换操作; - 不同 RDD 实体之间形成链条式的依赖结构以便支持高效的容错机制; - 针对键值对形式的数据提供专门定制化的哈希/范围划分策略; - 尽量减少网络传输开销从而提升整体性能表现。 ##### (b) 创建 RDD 方法 创建一个简单的 RDD 对象通常有两种途径: 1. 使用 `sc.parallelize()` 函数直接从内存列表初始化; 2. 加载外部存储文件作为输入源生成对应 RDD 表达式。 下面展示一段代码片段用于演示这两种方法的具体实现过程: ```python from pyspark import SparkContext # 初始化 Spark 上下文环境 sc = SparkContext(appName="Example") # 方式一:由本地数组构造 RDD data_list = [1, 2, 3, 4, 5] rdd_from_list = sc.parallelize(data_list) # 方式二:读取文本文件生成 RDD file_path = "/path/to/sample.txt" rdd_from_file = sc.textFile(file_path) ``` #### 3. 示例作业解析 接下来给出几个具体案例来说明如何运用所学理论解决实际问题。 ##### (a) 数据去重 假设我们有一组整数序列需要找出其中唯一的成员,则可通过调用内置 action 和 transformation 组合达成目标如下所示: ```python original_rdd = sc.parallelize([1, 2, 3, 2, 4, 3]) distinct_rdd = original_rdd.distinct() result = distinct_rdd.collect() # 输出唯一值组成的列表 print(result) # 结果应为 [1, 2, 3, 4] ``` 此处 `.distinct()` 方法正是用来移除冗余记录的有效工具。 ##### (b) 合并排序 如果面临多路流式数据接入需时,往往还需要考虑后续排列顺序调整环节。这里采用 union + sortBy 功能组合即可轻松搞定: ```python stream_a = sc.parallelize(["apple", "banana"]) stream_b = sc.parallelize(["orange", "grape"]) merged_stream = stream_a.union(stream_b).sortBy(lambda word: word.lower()) sorted_words = merged_stream.collect() print(sorted_words) # 应显示 ["apple", "banana", "grape", "orange"] ``` 此部分涉及到了两个重要动作——`union` 和 `sortBy`,前者负责拼接不同来源的内容,后者则按照自定义比较器重新安排位置次序。 ##### (c) 平均值 最后来看一组随机浮点数样本计算其均值得到最终结论的过程: ```python nums = sc.parallelize([10.5, 20.75, 30.8]) sum_and_count = nums.mapValues(lambda v: (v, 1)).reduceByKey( lambda a, b: (a[0]+b[0], a[1]+b[1])) average_value = sum_and_count.values().map(lambda pair: pair[0]/pair[1]).first() print(f"The average is {average_value}") ``` 注意这里的技巧在于借助 map-reduce 思想分解复杂度较高的数学公式表达成易于管理的小单元再逐层累加直至得到全局解法。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elvis_hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值