莎士比亚文集词频统计并行化算法

声明:本博客内容由本人经过实验楼实验得来。

题目描述

在给定的莎士比亚文集上(多个文件),根据规定的停词表,统计出现频率最高的 100 个单词。所谓的停词表,即在词表中的词语并不统计他的频率。

莎士比亚文集中具有多个章节,因此需要用到并行化的方法,这里使用Spark进行处理。

数据下载

# 莎士比亚文集:
wget http://labfile.oss.aliyuncs.com/courses/456/shakespear.zip
# 停词表:
wget http://labfile.oss.aliyuncs.com/courses/456/stopword.txt

编程模型

Spark上开发的应用程序都是由一个driver programe构成,这个所谓的驱动程序在Spark集群通过跑main函数来执行各种并行操作。集群上的所有节点进行并行计算需要共同访问一个分区元素的集合,这就是RDD(RDD resilient distributed dataset)弹性分布式数据集。RDD可以存储在内存或磁盘中,具有一定的容错性,可以在节点宕机重启后恢复。RDD可以从文件系统或HDFS中的文件创建,也可以从Scala或Python集合中创建。

主要针对RDD进行各种操作,程序中的步骤:

提取数据到RDD中,在本实验中我们将莎士比亚文集和停词表文件转换成RDD
1. 转换(transformations)操作:将已存在的数据集转换成新的数据集,例如map。转换是惰性的,不会立刻计算结果,仅仅记录转换操作应用的目标数据集,当动作需要一个结果时才计算。在本实验中我们需要转换文集RDD和停词表RDD。
2. 动作(actions) :数据集计算后返回一个值给驱动程序,例如reduce。本实验中需要对统计词频map的结果进行reduce操作。

程序实现

读入文件:
# 打开pyspark
[yqtao@localhost ~]$ pyspark
# 读入数据
>>> inputFiles = "/home/yqtao/bigdata/shakespear/*"
>>> stopWordFile = "/home/yqtao/bigdata/stopword.txt"
# 创建RDD文件
>>> inputRDD = sc.textFile(inputFiles)
>>> stopRDD = sc.textFile(stopWordFile)
处理特殊符号

输入的文件内容里除了英文单词之外,还有下面的特殊符号,这些符号不应该计算到统计中。

  • 制表符
  • 反斜线
  • 句号
  • 逗号
  • 竖线 |
  • 中括号
  • 问号
  • 破折号
  • 叹号
  • 分号
  • 其他英文符号

其策略就是用空格替换这些特出的符号,然后在将其划分为单词。

# targetList是一个列表,包含这些特殊的符号
# 定义一个函数实现此功能
# python真的好强大!!!!
>>> targetList = list('\t\().,?[]!;|') + ['--']
>>> 
>>> def replaceAndSplit(s):
...     for c in targetList:
...         s = s.replace(c, " ")
...     return s.split()

# 通过flatMap调用自定义的函数
# 即此时的RDD中没有了这些特殊的符号
>>>inputRDDv1 = inputRDD.flatMap(replaceAndSplit)
处理停词表

将停词表读入列表中:

# 去除空行,获得列表
>>> stopList = stopRDD.map(lambda x: x.strip()).collect()

如果输入的文件中有停词表中的词,则将其去除,采用RDD的filter方法。

>>>inputRDDv2 = inputRDDv1.filter(lambda x: x not in stopList)
Map操作

所谓的map操作转换操作,这点要深刻理解。
给每个单词组成元组(x,1),表示单词x出现了1次。

>>>inputRDDv3 = inputRDDv2.map(lambda x: (x,1))
Reduce操作

即计算操作,将相同的词进行统计频数。这里是对第二个数进行统计的。

# 导入add
>>>from operator import add
>>>inputRDDv4 = inputRDDv3.reduceByKey(add)
# 保存,可查看结果
# 可以看到他是分布式的存储的
>>>inputRDDv4.saveAsTextFile('/tmp/v4output')
TopK操作

即要统计出现最高频率的100个单词。

# 首先将单词频率与单词进行交换,这样就可以对频率进行排序
>>>inputRDDv5 = inputRDDv4.map(lambda x: (x[1], x[0]))
# 进行降序排列ascending=False表示降序
>>>inputRDDv6 = inputRDDv5.sortByKey(ascending=False)

排完序后,取单词:

# 交换位置,去key值
>>>inputRDDv7 = inputRDDv6.map(lambda x: (x[1], x[0])).keys()
# 取前100个单词
>>>top100 = inputRDDv7.take(100)
# 存储操作
>>>outputFile = "/tmp/result"
>>>result = sc.parallelize(top100)
>>>result.saveAsTextFile(outputFile)

完整的python代码

  1 #!/usr/bin/python
  2 # coding: utf-8
  3 from pyspark import SparkContext,SparkConf
  4 from operator import add
  5 import sys
  6 appName="WordCount"
  7 conf=SparkConf().setAppName(appName).setMaster("local")
  8 sc=SparkContext(conf=conf)
  9 inputFiles = "/home/yqtao/bigdata/shakespear/*"
  1 #!/usr/bin/python
  2 # coding: utf-8
  3 from pyspark import SparkContext,SparkConf
  4 from operator import add
  5 import sys
  6 appName="WordCount"
  7 conf=SparkConf().setAppName(appName).setMaster("local")
  8 sc=SparkContext(conf=conf)
  9 inputFiles = "/home/yqtao/bigdata/shakespear/*"
 10 stopWordFile = "/home/yqtao/bigdata/stopword.txt"
 11 outputFile = "/tmp/result"
 12 
 13 targetList=list('\t\().,?;|')+['--']
 14 
 15 def replaceAndSplit(s):
 16     for c in targetList:
 17         s=s.replace(c," ")
 18     return s.split()    
 19     
 20     
 21 inputRDD=sc.textFile(inputFiles)
 22 stopRDD=sc.textFile(stopWordFile)
 23 stopList = stopRDD.map(lambda x:x.strip()).collect()
 24     
 25 inputRDD1=inputRDD.flatMap(replaceAndSplit)
 26 inputRDD2=inputRDD1.filter(lambda x: x not in stopList)
 27 inputRDD3=inputRDD2.map(lambda x: (x,1))
 28 inputRDD4=inputRDD3.reduceByKey(add)
 29 inputRDD5=inputRDD4.map(lambda x:(x[1],x[0]))
 30 inputRDD6=inputRDD5.sortByKey(ascending=False)
 31 inputRDD7=inputRDD6.map(lambda x: (x[1],x[0])).keys()
 32 top100=inputRDD7.take(100)
 33 result=sc.parallelize(top100)
 34 result.saveAsTextFile(outputFile)

运行:

[yqtao@localhost bigdata]$ spark-submit shake.py

打开结果如下所示:

  1 I
  2 And
  3 him
  4 thou
  5 so
  6 The
  7 thy
  8 all
  9 To
 10 by
 11 thee
 12 That
 13 we
 14 But
 15 what
 16 good
 17 O
 18 more
 19 they
 20 What
 21 lord
 22 now
 23 love
 24 them
 25 A
 26 KING
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值