mapreduce python实例_MapReduce程序实例(python)

问题背景

现在有两份数据,file1是校园新闻版块,每一条新闻点击记录;file2是校园新闻版块使用活跃度高的学生记录。用mr统计出某一天的点击记录里,使用ios/android手机的活跃学生的总的点击次数

原始数据格式如下:

file 1,校园新闻点击记录,记录了每一次学生点击校园新闻的行为

格式:学号\t姓名\t手机端\t新闻id\新闻关键词

20170001 xiaoming android 331 学费

20170002 xiaohong ios 332 食堂

20170003 xiaohua android 333 考研

20170001 xiaoming android 222 评优

20170001 xiaoming android 225 学费

20170003 xiaohua android 111 期末考试

20170002 xiaohong ios 117 空调安装

...

file2,校园新闻活跃学生记录,记录了对校园新闻版块点击活跃度高的学生信息

格式:格式:学号\t姓名\t年龄\t手机端

20170001 xiaoming 20 android

20170002 xiaohong 19 ios

20170001 xiaoqiang 20 android

...

问题分析

1、key的选择:选取学号+手机端共同作为key。学号是用于对是否活跃用户的判断,手机端是用于统计时的分类。注意,这里如果仅仅将手机端作为key有一个坏处,就是key值将只有两种,这样不利于将海量的数据分为多个小部分处理,因此选择学号+手机端共同作为key。

2、关键点:在对每一行数据进行处理时,利用两份数据,做好是否活跃用户的标记;在对同一个key进行处理时,根据前一步处理的结果,判断是否进行累加。

代码实现

1、mapper.py

解析原始数据,将其处理为一系列的键值对(key-value pair),这里选取"学号_手机端"作为key。

import sys

def main():

"""

mapper

"""

for line in sys.stdin:

data = line.strip().split("\t")

if len(data) == 5:

student_id = data[0]

os_name = data[2]

key = student_id + '_' + os_name

print"\t".join([key,"file1"])

elif len(data) == 4:

student_id = data[0]

os_name = data[-1]

key = student_id + '_' + os_name

print"\t".join([key,"file2"])

if __name__ == "__main__":

main()

2、reducer.py

由MapReduce框架的机制,同一个key的所有数据都会被传给同一个reducer,同一个reducer可以接受多个键值对。

reducer将相同键的一组值,进行处理产生一组规模更小的值(如累加得到一个值)。

import sys

import json

dic_result = {'android':0, 'ios':0}

pre_key = ""

def post_deal(pre_key):

"""

相同key的数据的处理

"""

global dic

os_name = pre_key.strip.split("\t")[1]

if 'click' in dic and dic['click'] == 'yes' and 'active' in dict and dic['active'] == 'yes':

dic_result[os_name] += 1

def deal(data):

"""

对每一行数据的处理

"""

if data[1] == "file1":

dic['click'] = 'yes'

if data[1] == "file2":

dic['active'] = 'yes'

def pre_deal():

"""

预处理,如将用于存储同一个key的一组value中间结果的字典置零

"""

global dic

dic = dict()

def main():

"""

reducer

"""

for line in sys.stdin:

data = line.strip().split("\t")

key = data[0]

#当同一个key的数据全部deal完,到下一个key时

if key != pre_key:

if pre_key != "":

#处理同一个key所有数据

post_deal(pre_key)

#处理完成后,预处理准备下一轮处理

pre_deal()

#将pre_key更新为下一个要处理的key

pre_key = key

#将同一个key的一组值按需要进行处理/整合

deal(data)

#处理最后一个key的数据

if pre_key != "":

post_deal(pre_key)

#打印结果

print json.dumps(dic_result)

if __name__ == "__main__":

main()

3、线下测试 cat file|map|sort|reduce

STEP1:测试map

cat file1_test file2_test | python mapper.py > map_out

测试中,map_out中的数据将如下所示:

20170001_andorid file1

20170002_ios file1

20170003_andorid file1

20170001_andorid file1

...

20170001_andorid file2

20170002_ios file2

...

STEP2:对map_out按照key(key默认放在第一列)排序,使相同key的数据在一起,然后测试reducer

cat map_out |sort -k1,1|python reducer.py > red_out

reducer的输出是json,形如:{'ios':1123, 'android':3333}

4、hadoop线上运行 run.sh

#!/bin/bash

WORKROOT="..."

HADOOP="hadoop客户端路径"

INPUT1="file1文件路径"

INPUT2="file2文件路径"

OUTPUT_DIR="输出的HDFS路径"

PYTHON="python路径"

#设置一系列参数,并启动MR任务

$HADOOP streaming \

-D mapred.map.tasks=200 \

-D mapred.job.map.capacity=400 \

-D mapred.red.tasks=100 \

-D mapred.job.red.capacity=400 \

-D mapred.job.priority=HIGH \

-D stream.num.map.output.key.fields=1 \

...

-partitionor ... \

-cacheArchive ... \

-input $INPUT1 \

-input $INPUT2 \

-output $OUTPUT_DIR \

-mapper "$PYTHON mapper.py" \

-reducer "$PYTHON reducer.py" \

-file $WORKROOT/mapper.py \

-flle $WORTROOT/reducer.py

#成功运行完成,创建一个空文件,加上成功的标签

if [ ${?} -eq 0 ]; then

$HADOOP fs -touchz $OUTPUT_DIR succuss.tag

部分参数的解释:

mapred.map.tasks:map数目

mapred.reduce.tasks:reduce数目

mapred.job.map.capacity:map并发数目

mapred.job.reduce.capacity:educe并发数目

stream.num.map.output.key.fields:设置map程序分隔符的位置,该位置之前的部分作为key,之后的部分作为value

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 MapReduce 编程实例: 假设我们有一个文本文件,其中每一行是一个单词。我们想要对这些单词进行计数,并且按照出现次数从大到小进行排序。 首先,我们需要编写 Map 函数,将每个单词映射到一个键值对。键是单词本身,值是 1(表示出现了一次): ```python def map_function(line): words = line.strip().split() for word in words: yield word, 1 ``` 然后,我们需要编写 Reduce 函数,将相同单词的计数相加: ```python def reduce_function(word, counts): yield word, sum(counts) ``` 最后,我们可以使用 Hadoop MapReduce 框架来执行这个程序,其中输入数据是一个文本文件,输出数据是一个按照单词出现次数排序的列表: ```python from mrjob.job import MRJob from mrjob.step import MRStep class WordCount(MRJob): def steps(self): return [ MRStep(mapper=self.map_function, reducer=self.reduce_function), MRStep(reducer=self.reduce_sort) ] def map_function(self, _, line): words = line.strip().split() for word in words: yield word, 1 def reduce_function(self, word, counts): yield word, sum(counts) def reduce_sort(self, word, counts): yield None, (sum(counts), word) def reducer_final(self, _, word_counts): for count, word in sorted(word_counts, reverse=True): yield word, count if __name__ == '__main__': WordCount.run() ``` 这个程序使用两个 MapReduce 步骤。第一个步骤是对每个单词计数,第二个步骤是对计数进行排序。 这只是一个简单的例子,实际的 MapReduce 程序可能更加复杂。但是,这个例子可以帮助你理解 MapReduce 的基本思想和编程模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值