RDD编程初级实践

RDD编程初级实践


前言

现在这个网络大环境,每个人每天都要产生海量的数据,处理存储这些数据是每个互联网公司不得不面对的难题,在这种需求下,人们创造了hadoop来解决存储的问题,而Spark就是人们对数据处理给出的答案,其中的RDD编程就是必须要了解学习的一个技术。其实每个人每天需要处理的数据大部分都是重复单一的,对于一整个数据集,RDD可以用少量代码命令解决一整个数据集的去重,统计,运算,拆分等操作,对于这样一个技术,在此做一个实验来加强自己的学习和实践。


一、数据来源、环境介绍

本次实验使用到的数据集:data.txt; A.txt; B.txt; Algorithm.txt; Database.txt; Python.txt。

实验环境:Ubuntu Kylin 16.04;Spark 2.4.7 ;Python 3.5.2

其他软件:FinaShell 3.9(使用这个软件就是为了方便,对实验结果和过程不会有任何影响)

二、实验步骤

1.复制所有数据文件到系统中

因为使用FinaShell,我能直接把数据文件复制进系统,也可以使用虚拟机的双向复制等其他方法,只要把数据集放到Ubuntu系统中即可。

本人把数据集放在/usr/local/spark/sparkdata目录下。
FinalShell主界面

2.配置pyspark环境

配置pyspark就不在此演示,网上很多教程。

3.数据处理过程与结果

实验一:处理data.txt文件

我们对学生成绩进行相应的查询计算和统计共七点要求,需要在pyspark shell界面中通过编程来操作:
pyspark shell
① 该系总共有多少学生:

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).map(lambda x:x[0])
// 由于要获得学生,而该数据集中唯一标志学生的是学生的名字
// 所以对RDD每一行进行遍历,将逗号作为分隔符,然后选择分割后的第一个元素,将结果返回为一个新的RDD
sum = res.distinct()
// 对RDD中的元素进行去重
sum.count()
// 返回RDD中的元素个数

运行结果
② 该系共开设了多少门课程;

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).map(lambda x:x[1])
// 由于要获得课程,将逗号作为分隔符,然后选择分割后的第二个元素,将结果返回为一个新的RDD
sum = res.distinct()
// 对RDD中的元素进行去重
sum.count()
// 返回RDD中的元素个数

运行结果
③ Tom同学的总成绩平均分是多少;

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).filter(lambda x:x[0] == 'Tom')
// 对RDD进行筛选,选出名字为Tom的
score = res.map(lambda x:int(x[2]))
// 将Tom每门课的成绩筛选出来作为一个新的RDD并将成绩转换为整数
sum_score = score.reduce(lambda x,y:x+y)
// 对成绩求和
num = res.count()
// 获得课程数
avg = sum_score/num
// 相除求得平均成绩
print(avg)
// 返回平均成绩

运行结果
④ 求每名同学的选修的课程门数;

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).map(lambda x:(x[0],1))
// 将每个同学的名字作为键,每出现一次说明选了一门课,所以将值设为1
each_res = res.reduceByKey(lambda x,y:x+y)
// 对上述RDD做聚合即可得到每个学生选修的课程门数
each_res.foreach(print)
// 输出每个学生的选课数目

运行结果
⑤ 该系DataBase课程共有多少人选修;

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).filter(lambda x:x[1] == 'DataBase')
// 筛选出选择数据库课程的学生
res.count()
// 对其计数则可得到选数据库课程的人数

运行结果
⑥ 各门课程的平均分是多少;

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).map(lambda x:(x[1],(int(x[2]),1)))
// 将每门课作为键,值为一个键值对,该键值对的键为成绩,值为1(用于后面计算平均值计数用)
temp = res.reduceByKey(lambda x,y:(x[0]+y[0],x[1]+y[1]))
// 对上述RDD做聚合,值的聚合返回一个二元组,第一个元素是该门课的成绩求和,第二个元素是选修该门课学生学生的人数
avg = temp.map(lambda x:(x[0],round(x[1][0]/x[1][1],2)))
// 做一个映射,将课程名作为第一个元素,每门课的总成绩除以选修该门课的总人数得到平均成绩作为第二个元素
avg.foreach(print)
// 输出每个学生的选课数目
// 输出各门课程的平均分

运行结果
⑦ 使用累加器计算共有多少人选了DataBase这门课。

lines = sc.textFile("file:///usr/local/spark/sparkdata/data.txt")
// 从本地文件系统中创建RDD
res = lines.map(lambda x:x.split(",")).filter(lambda x:x[1] == 'DataBase')
// 筛选出选择数据库课程的学生,为了能使用累加器,将每个项后面都加个1
accum = sc.accumulator(0)
// 初始化一个累加器
res.foreach(lambda x:accum.add(1))
// 通过累加器对选修数据库课程的人数进行累加
accum.value
// 输出累加后的人数

运行结果

实验二:合并A.txt,B.txt数据集

我们需要对两个数据集进行集合与去重,并将结果输出成一个新的数据集。

①进入/usr/local/spark/mycode/remdup目录,如果没有相应文件夹可以自行创建,在目录下创建一个脚本文件remdup.py,此脚本文件可以存放在其他目录下,不影响结果。

②使用vim编辑remdup.py文件,输入以下内容:

from pyspark import SparkContext
sc = SparkContext('local','remdup')
lines1 = sc.textFile("file:///usr/local/spark/sparkdata/A.txt")
lines2 = sc.textFile("file:///usr/local/spark/sparkdata/B.txt")
lines = lines1.union(lines2)
distinct_lines = lines.distinct()
res = distinct_lines.sortBy(lambda x:x)
res.repartition(1).saveAsTextFile("file:///usr/local/spark/sparkdata/result")

编辑脚本文件
注意:其中lines1与lines2中的文件路径可以根据自己实际存放路径做出变更,最后一行保存文件路径也可更改,并且文件夹会自己创建,所以不用单独创建。

③使用命令python3 remdup.py运行脚本文件,注意执行程序时先退出spark shell,否则会出现“地址已在使用”的错误。
运行脚本文件
④本实验在/usr/local/spark/spark/sparkdata/result路径下会有结果文件part-00000。


注意:结果文件是根据脚本文件的路径而存放。

⑤检查结果文件,判断是否达到实验预期
结果

实验三:求Algorithm.txt; Database.txt; Python.txt平均数

三个数据我们要编写Spark独立应用程序求出所有学生的平均成绩,并输出到一个新文件中,此项实验与第二个实验几乎一样,只有处理数据的程序不同。

①首先在路径/usr/local/spark/mycode/avgscore中创建avgscore.py脚本文件

②使用命令vim avgscore.py编辑脚本文件,输入以下内容:

from pyspark import SparkContext
sc = SparkContext('local','avgscore')
lines1 = sc.textFile("file:///usr/local/spark/sparkdata/Algorithm.txt")
lines2 = sc.textFile("file:///usr/local/spark/sparkdata/Database.txt")
lines3 = sc.textFile("file:///usr/local/spark/sparkdata/Python.txt")
lines = lines1.union(lines2).union(lines3)
distinct_lines = lines.distinct()
lines4 = distinct_lines.sortBy(lambda x:x).filter(bool)
data = lines4.map(lambda x:x.split(" ")).map(lambda x:(x[0],(int(x[1]),1)))
res = data.reduceByKey(lambda x,y:(x[0]+y[0],x[1]+y[1]))
result = res.map(lambda x:(x[0],round(x[1][0]/x[1][1],2)))
result.repartition(1).saveAsTextFile("file:///usr/local/spark/sparkdata/result1")

③使用命令python3 avgscore.py运行脚本文件,注意执行程序时先退出spark shell,否则会出现“地址已在使用”的错误。

④本次实验在/usr/local/spark/spark/sparkdata/result1路径下会有结果文件part-00000


⑤检查结果文件,判断是否达到实验预期


总结

本次实验需要在Ubuntu系统环境下,对与本地数据进行处理,查询,计算,统计等操作。首先RDD的创建分为,文件系统加载创建,HDFS加载上传和通过并行集合(列表)创建三种方法,为了简便,本实验实验第一种方法。接着便是RDD转换操作,通过不同的转换语句可以对数据进行排列去重等操作,从而实现对数据的处理。转换操作完成后要接着行动操作,行动操作才是真正触发计算的地方,Spark程序执行到行动操作时,才会执行真正的计算,从文件中加载数据,完成一次又一 次转换操作,最终,完成行动操作得到结果。除了以上两种操作,我们还要了解惰性机制,所谓的“惰性机制”是指,整个转换过程只是记录了转换的轨迹,并不会发生真正的计算,只有遇到行动操作时,才会触发“从头到尾”的真正的计算。对于本次实验学习以上几点即可,除此之外,Spark编程还有持久化和分区,这两个其实就是为了运行效率和存储的考良,本次实验的据量太小,还未到需要优化运行速度和考虑存储大小,所以了解即可。

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spark Streaming RDD 编程主要涉及到以下几个方面: 1. 创建 StreamingContext 对象:首先需要创建一个 StreamingContext 对象,设置应用程序名称、批处理间隔等参数。 ```scala val conf = new SparkConf().setAppName("Streaming example") val ssc = new StreamingContext(conf, Seconds(1)) ``` 2. 创建输入 DStream:使用 StreamingContext 对象创建一个输入 DStream。这个 DStream 可以从多个数据源创建,如 Kafka、Flume、Kinesis、HDFS 等。 ```scala val lines = ssc.socketTextStream("localhost", 9999) ``` 3. 转换操作:通过对输入 DStream 进行一系列转换操作,得到需要的结果。转换操作包括 map、filter、reduceByKey、window 等。 ```scala val words = lines.flatMap(_.split(" ")) val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _) ``` 4. 输出操作:对转换后的 DStream 进行输出操作,输出结果可以写入 HDFS、Kafka、Cassandra 等存储系统,或者直接打印在控制台。 ```scala wordCounts.print() ``` 5. 启动 StreamingContext:最后需要启动 StreamingContext,并等待程序运行结束。 ```scala ssc.start() ssc.awaitTermination() ``` 完整的 Spark Streaming RDD 编程示例代码如下: ```scala import org.apache.spark.SparkConf import org.apache.spark.streaming.{Seconds, StreamingContext} object SparkStreamingRDD { def main(args: Array[String]): Unit = { val conf = new SparkConf().setAppName("Streaming example") val ssc = new StreamingContext(conf, Seconds(1)) val lines = ssc.socketTextStream("localhost", 9999) val words = lines.flatMap(_.split(" ")) val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _) wordCounts.print() ssc.start() ssc.awaitTermination() } } ``` 这个例子从本地 9999 端口读取输入数据,将输入数据拆分成单词,并计算每个单词出现的次数。最后将结果打印在控制台。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值