计算均值mean的MapReduce程序Computing mean with MapReduce
In this post we'll see how to compute the mean of the max temperatures of every month for the city of Milan.
The temperature data is taken from http://archivio-meteo.distile.it/tabelle-dati-archivio-meteo/, but since the data are shown in tabular form, we had to sniff the HTTP conversation to see that the data come from this URL and are in JSON format.
Using Jackson, we could transform this JSON into a format simpler to use with Hadoop: CSV. The result of conversion is this:
01012000,-4.0,5.0
02012000,-5.0,5.1
03012000,-5.0,7.7
04012000,-3.0,9.7
...
If you're curious to see how we transformed it, take a look at the source code.
Let's look at the mapper class for this job:
public static class MeanMapper extends Mapper<Object, Text, Text, SumCount> {
private final int DATE = 0;
private final int MIN = 1;
private final int MAX = 2;
private Map<Text, List<Double>> maxMap = new HashMap<>();
@Override
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
// gets the fields of the CSV line
String[] values = value.toString().split((","));
// defensive check
if (values.length != 3) {
return;
}
// gets date and max temperature
String date = values[DATE];
Text month = new Text(date.substring(2));
Double max = Double.parseDouble(values[MAX]);
// if not present, put this month into the map
if (!maxMap.containsKey(month)) {
maxMap.put(month, new ArrayList<Double>());
}
// adds the max temperature for this day to the list of temperatures
maxMap.get(month).add(max);
}
@Override
protected void cleanup(Context context) throws IOException, InterruptedException {
// loops over the months collected in the map() method
for (Text month: maxMap.keySet()) {
List<Double> temperatures = maxMap.get(month);
// computes the sum of the max temperatures for this month
Double sum = 0d;
for (Double max: temperatures) {
sum += max;
}
// emits the month as the key and a SumCount as the value
context.write(month, new SumCount(sum, temperatures.size()));
}
}
}
How we've seen in the last posts (about optimization and combiners), in the mapper we first put values into a map, and when the input is over, we loop over the keys to sum the values and to emit them. Note that we use the SumCount class, which is a utility class that wraps the two values we need to compute a mean: the sum of all the values and the number of values.
A common error in this kind of computation is making the mapper directly emit the mean; let's see what it can happen if we suppose to have a dataset like this:
01012000,0,10.0
02012000,0,20.0
03012000,0,2.0
04012000,0,4.0
05012000,0,3.0
and two mappers, which will receive the first two and the last three lines respectively. The first mapper will compute a mean of 15.0, given from (10.0 + 20.0) / 2. The second will compute a mean of 3.0, given from (2.0 + 4.0 + 3.0) / 3. When the reducer receive this two values, it sums them together and divide by two, so that the mean will be: 9.0, given from (15.0 + 3.0) / 2. But the correct mean for the values in this example is 7.8, which is given from (10.0 + 20.0 + 4.0 + 2.0 + 3.0) / 5.
This error is due to the fact that any mapper can receive any number of lines, so the value it will emit is only a part of the information needed to compute a mean.
If instead of emitting the mean we emit the sum of the values and the number of values, we can overcome the problem. In the example we saw before, the first mapper will emit the pair (30.0, 2) and the second (9.0, 3); if we sum the values and divide it by the sum of the numbers, we obtain the right result.
Let's get back to our job and look at the reducer:
public static class MeanReducer extends Reducer<text, sumcount,="" text,="" doublewritable=""> {
private Map<text, sumcount=""> sumCountMap = new HashMap<>();
@Override
public void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
SumCount totalSumCount = new SumCount();
// loops over all the SumCount objects received for this month (the "key" param)
for (SumCount sumCount : values) {
// sums all of them
totalSumCount.addSumCount(sumCount);
}
// puts the resulting SumCount into a map
sumCountMap.put(new Text(key), totalSumCount);
}
@Override
protected void cleanup(Context context) throws IOException, InterruptedException {
// loops over the months collected in the reduce() method
for (Text month: sumCountMap.keySet()) {
double sum = sumCountMap.get(month).getSum().get();
int count = sumCountMap.get(month).getCount().get();
// emits the month and the mean of the max temperatures for the month
context.write(month, new DoubleWritable(sum/count));
}
}
}
The reducer is simpler because it has just to retrieve all the SumCount objects emitted from the reducers and add them together. After receiving the input, it loops over the map of the SumCount objects and emits the month and the mean.
from: http://andreaiacono.blogspot.com/2014/04/computing-mean-with-mapreduce.html
计算均值mean的MapReduce程序Computing mean with MapReduce的更多相关文章
- 用Python语言写Hadoop MapReduce程序Writing an Hadoop MapReduce Program in Python
In this tutorial I will describe how to write a simple MapReduce program for Hadoop in the Python pr ...
- 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)
上一篇我们学习了MapReduce的原理,今天我们使用代码来加深对MapReduce原理的理解. wordcount是Hadoop入门的经典例子,我们也不能免俗,也使用这个例子作为学习Hadoop的第 ...
- HDFS设计思路,HDFS使用,查看集群状态,HDFS,HDFS上传文件,HDFS下载文件,yarn web管理界面信息查看,运行一个mapreduce程序,mapreduce的demo
26 集群使用初步 HDFS的设计思路 l 设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l 在大数据系统中作用: 为各类分布式 ...
- [python]使用python实现Hadoop MapReduce程序:计算一组数据的均值和方差
这是参照<机器学习实战>中第15章“大数据与MapReduce”的内容,因为作者写作时hadoop版本和现在的版本相差很大,所以在Hadoop上运行python写的MapReduce程序时 ...
- 怎样通过Java程序提交yarn的mapreduce计算任务
因为项目需求,须要通过Java程序提交Yarn的MapReduce的计算任务.与一般的通过Jar包提交MapReduce任务不同,通过程序提交MapReduce任务须要有点小变动.详见下面代码. 下面 ...
- 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行
[TOC] 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行 程序源码 import java.io.IOException; import java.util. ...
- mapreduce程序编写(WordCount)
折腾了半天.终于编写成功了第一个自己的mapreduce程序,并通过打jar包的方式运行起来了. 运行环境: windows 64bit eclipse 64bit jdk6.0 64bit 一.工程 ...
- 基于Hbase数据的Mapreduce程序环境开发
一.实验目标 编写Mapreduce程序,以Hbase表数据为Map输入源,计算结果输出到HDFS或者Hbase表中. 在非CDH5的Hadoop集群环境中,将编写好的Mapreduce程序整个工程打 ...
- 从零开始学习Hadoop--第2章 第一个MapReduce程序
1.Hadoop从头说 1.1 Google是一家做搜索的公司 做搜索是技术难度很高的活.首先要存储很多的数据,要把全球的大部分网页都抓下来,可想而知存储量有多大.然后,要能快速检索网页,用户输入几个 ...
随机推荐
- 使用spring-boot-maven-plugin插件打包spring boot项目
在spring-boot项目中使用spring-boot-maven-plugin插件进行打包,输出可执行JAR包.项目包含多个模块,当打完包后在本地的maven仓库中发现输出的可执行JAR非常小,并 ...
- bzoj [SDOI2009]学校食堂Dining
感觉这个状压dp比较难想.. dp[ i ][ s ][ k ] 表示前i - 1个都排好了, 从i开始的7个的取没取的状态为s, 且最后一个相对i的位置为k的最少花费. 状态转移方程 if(s &a ...
- poj1847 Tram(Dijkstra || Floyd || SPFA)
题目链接 http://poj.org/problem?id=1847 题意 有n个车站,编号1~n,每个车站有k个出口,车站的出口默认是k个出口中的第一个,如果不想从默认出口出站,则需要手动选择出站 ...
- CSUOJ 1781 阶乘除法
Description 输入两个正整数 n, m,输出 n!/m!,其中阶乘定义为 n!= 1*2*3*...*n (n>=1). 比如,若 n=6, m=3,则 n!/m!=6!/3!=720 ...
- NetCore+Dapper WebApi架构搭建(四):仓储的依赖注入
上一节我们讲到实体,仓储接口和仓储接口的实现需要遵循约定的命名规范,不仅是规范,而且为了依赖注入,现在我们实现仓储的依赖注入 在NetCore WebApi项目中新添加一个文件夹(Unit),当然你也 ...
- 01-学前入门VS各个组成部分
1)快捷打开运行窗口(Windows+R) 里面输入devenv命令快捷打开VS 2)解决方案,项目及类之间的关系(解决方案包含项目-项目包含-类) 例如可以这样比喻: 解决方案:相当于公司 项目:相 ...
- 写在OI退役后和高中毕业前的一些话
更新日志: 2017.02.13 开坑 2017.02.13 更新[零][壹] 2017.02.14 更新[贰] 2017.02.26 更新[叁][肆] 2017.03.04 锅多如狗,停更一周 20 ...
- 【枚举】【贪心】Codeforces Round #482 (Div. 2) B. Treasure Hunt
题意:给你3个字符串,3个人各对自己的字符串执行n轮操作,每一次选择一个字符变为任意一个和原来不同的字符.最后问你谁能使自己的串中的任意重复子串出现的次数最大化. 显然只需关注字符而非子串. 枚举每个 ...
- Loj10167 HDU2089 不要62
题目描述 杭州人称那些傻乎乎粘嗒嗒的人为 626262(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士 ...
- git服务器安装和配置
http://www.cnblogs.com/dee0912/p/5815267.html