Python Mapreduce实例——去重

任务目标

1.准确理解mapreduce去重的设计原理

2.熟练掌握mapreduce去重的程序编写

3.学会自己编写MapReduce去重代码解决实际问题

相关知识

“数据去重”主要是为了掌握和利用并行化思想来对数据进行有意义的筛选。统计大数据集上的数据种类个数、从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据去重。

数据去重的最终目标是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。在MapReduce流程中,map的输出<key,value>经过shuffle过程聚集成<key,value-list>后交给reduce。我们自然而然会想到将同一个数据的所有记录都交给一台reduce机器,无论这个数据出现多少次,只要在最终结果中输出一次就可以了。具体就是reduce的输入应该以数据作为key,而对value-list则没有要求(可以设置为空)。当reduce接收到一个<key,value-list>时就直接将输入的key复制到输出的key中,并将value设置成空值,然后输出<key,value>。

MaprReduce去重流程如下图所示:

在这里插入图片描述

系统环境

Linux Ubuntu 16.04

Python 3.5

jdk-7u75-linux-x64

hadoop-2.6.0-cdh5.4.5

PyCharm

任务内容

现有某电商网站的数据文件,文件名为buyer_favorite1,记录着用户收藏的商品以及收藏的日期。

文件buyer_favorite1中包含(用户id,商品id,收藏日期)三个字段,数据内容以“\t”分割,样例数据内容如下:

view plain copy
用户id 商品id 收藏日期
10181 1000481 2010-04-04 16:54:31
20001 1001597 2010-04-07 15:07:52
20001 1001560 2010-04-07 15:08:27
20042 1001368 2010-04-08 08:20:30
20067 1002061 2010-04-08 16:45:33
20056 1003289 2010-04-12 10:50:55
20056 1003290 2010-04-12 11:57:35
20056 1003292 2010-04-12 12:05:29
20054 1002420 2010-04-14 15:24:12
20055 1001679 2010-04-14 19:46:04
20054 1010675 2010-04-14 15:23:53
20054 1002429 2010-04-14 17:52:45
20076 1002427 2010-04-14 19:35:39
20054 1003326 2010-04-20 12:54:44
20056 1002420 2010-04-15 11:24:49
20064 1002422 2010-04-15 11:35:54
20056 1003066 2010-04-15 11:43:01
20056 1003055 2010-04-15 11:43:06
20056 1010183 2010-04-15 11:45:24
20056 1002422 2010-04-15 11:45:49
20056 1003100 2010-04-15 11:45:54
20056 1003094 2010-04-15 11:45:57
20056 1003064 2010-04-15 11:46:04
20056 1010178 2010-04-15 16:15:20
20076 1003101 2010-04-15 16:37:27
20076 1003103 2010-04-15 16:37:05
20076 1003100 2010-04-15 16:37:18
20076 1003066 2010-04-15 16:37:31
20054 1003103 2010-04-15 16:40:14
20054 1003100 2010-04-15 16:40:16
编写MapReduce程序,根据商品id进行去重,统计用户收藏商品中都有哪些商品被收藏。

结果数据如下:

view plain copy
商品id
1003326
1003290
1003066
1010178
1002422
1003103
1010675
1001368
1003055
1010183
1003101
1001679
1003292
1003100
1002061
1001560
1002429
1003094
1000481
1003289
1002427
1002420
1003064
1001597

任务步骤

1.切换到/apps/hadoop/sbin目录下,启动hadoop进程。

view plain copy
cd /apps/hadoop/sbin

./start-all.sh
2. 在Linux本地新建/data/python_mapreduce2目录。

view plain copy
mkdir -p /data/python_mapreduce2
3.切换到/data/python_mapreduce2目录下,将样本数据写成txt文档 使用远程工具添加进去

view plain copy
cd /data/python_mapreduce2

4.首先在hdfs上新建/python_mapreduce2/in目录,然后将Linux本地/data/python_mapreduce2目录下的buyer_favorite1文件导入到hdfs的/python_mapreduce2/in目录中。

view plain copy
hadoop fs -mkdir -p /python_mapreduce2/in

hadoop fs -put /data/python_mapreduce2/buyer_favorite1 /python_mapreduce2/in
5.打开PyCharm,新建项目。

创建Python项目,项目位置:/data/python_mapreduce2。

在这里插入图片描述

6.在项目名python_mapreduce2下,新建mapper和reducer python文件。

在这里插入图片描述

先创建以mapper命名的文件
在这里插入图片描述

再创建以reducer命名的文件

在这里插入图片描述

7.描述其设计思路。

数据去重的目的是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。自然想到将相同key值的所有value记录交到一台reduce机器,让其无论这个数据出现多少次,最终结果只输出一次。

8.打开mapper.py文件,并使用以下代码作为内容。

view plain copy
#!/usr/bin/python3
#Filename:mapper.py

import sys

def read_input(file_obj):
for line in file_obj:
yield line.split()

def main(separator=’\t’):
data = read_input(sys.stdin)
for words in data:
print(’%s%s%d’ % (words[1], separator, 1))

if name == “main”:
main()
第1~3行:设置文件执行方式,文件编码为utf-8,当前文件名字,导入sys模块。

第6~8行:read_input()生成器函数,接收一个标准输入对象,迭代这个标准输入对象,使用yield关键字返回一个拆分后的列表对象。

第10~18行:main()接收一个separator默认参数,data等于read_input()返回的生成器对象,迭代data对象,data迭代一次在生成器里拿一个返回值,列表索引的方式取出的商品id字段设置为key,设置value为1,然后直接输出<key,value>。

生成器序列中的元素在你确实需要它的时候才会生成。这会很有用,当你手头上计算资源昂贵或内存紧缺。

9.打开reducer.py文件,并使用以下代码作为内容。

view plain copy
#!/usr/bin/python3
#Filename:reducer.py
from operator import itemgetter
import sys

def read_file(file_obj, separator):
for line in file_obj:
yield line.strip().split(separator, 1)

def main(separator=’\t’):
data = read_file(sys.stdin, separator)
uniq = set()
for line in data:
word, count = line
uniq.add(word)

for word in uniq:
print(word)

if name == ‘main’:
main()
第1~4行:设置文件执行方式,文件编码为utf-8,当前文件名字,导入sys、itemgetter模块。

第6~8行:read_input()生成器函数,接收一个标准输入对象参数和分隔符参数,迭代这个标准输入对象,使用yield关键字返回一个拆分后的列表对象。

第13~26行:main()接收一个separator默认参数,data等于read_input()返回的生成器对象,创建一个uniq集合对象,集合本身具有去除功能,迭代data对象,data迭代一次在生成器里拿一个返回值,把每个值添加到uniq集合对象中,最后循环打印结果。

10.运行MapReduce,先加执行权限,shell下执行下面命令:

view plain copy
chmod -R +x /data/python_mapreduce2/
11.shell下执行Hadoop MapReduce程序:

view plain copy
hadoop jar /apps/hadoop/share/hadoop/tools/lib/hadoop-streaming-2.6.0-cdh5.4.5.jar \
-file /data/python_mapreduce2/mapper.py \
-mapper /data/python_mapreduce2/mapper.py \
-file /data/python_mapreduce2/reducer.py \
-reducer /data/python_mapreduce2/reducer.py \
-input /python_mapreduce2/in/buyer_favorite1 \
-output /python_mapreduce2/out
file:文件路径

mapper:映射器程序路径

reducer:简化器文件路径

input:输入

output:输出

12.待执行完毕后,打开终端,查看hdfs目录程序输出的实验结果。

view plain copy
hadoop fs -ls /python_mapreduce2/out
hadoop fs -cat /python_mapreduce2/out/part-00000
在这里插入图片描述

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Mapreduce实例-WordCount是一个经典的MapReduce程序,用于统计文本中每个单词出现的次数。它的工作原理是将输入的文本划分为多个片段,每个片段由多个键值对组成,其中键是单词,值是1。然后通过Map阶段将每个片段中的单词提取出来,并将每个单词映射为键值对,其中键是单词,值是1。接下来,通过Shuffle和Sort阶段将具有相同单词的键值对聚集在一起。最后,通过Reduce阶段将相同单词的计数值进行累加,得到每个单词的总次数。 以下是一个示例代码片段,展示了WordCount程序的基本结构和关键组件: ```java import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class WordCount { public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(Object key, Text value, Context context) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } } public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable(); public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } result.set(sum); context.write(key, result); } } public static void main(String[] args) throws Exception { Job job = Job.getInstance(); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值