Hadoop - 国内各站点最高温度、气压和风速统计

时间:2022-09-05 15:04:05

版权说明:  本文章版权归本人及博客园共同所有,转载请标明原文出处(http://www.cnblogs.com/mikevictor07/),以下内容为个人理解,仅供参考。

一、简介

该实例统计国内各个站点的最高温度(为节省篇幅只以温度为例,可稍作修改即可统计气压与风速),数据来源于汇总在NCDC的天气气球数据集中(包含世界大量数据集,该实例只分析国内站点,数据对外公开,可下载)。

二、数据准备与预处理

从NCDC下载的天气气球数据集(ftp://ftp.ncdc.noaa.gov/pub/data/igra或http://www1.ncdc.noaa.gov/pub/data/igra/ , 压缩为gz包)如下,可见并不适合Hadoop的MR模块处理,需要进行预处理(本例下载数据gz包总大小为293MB,解压缩后为1.43GB):

#5928719630901009999   5
10 85000 1481B 202B-9999 190 20
10 70000 3139B 142B-9999 180 20
10 50000 5880B -55B-9999 60 30
10 40000 7605B -142B-9999 100 40
10 30000 9750B -255B-9999 100 70
#5928719630901129999 7
10 85000 1481B 215B-9999 320 20
10 70000 3142B 132B-9999 300 10
10 50000 5889B -35B-9999 50 30
10 40000 7620B -125B-9999 100 40
10 30000 9759B -275B-9999 70 60
10 20000 12561B -482B-9999 90 110
10 10000 16788B -785B-9999 90 100

首先需要阅读下载相关目录的readme.txt,才能站点相关字段的含义,温度数据已经*10(为了保留一位小数)

以该数据为例(其中的 9999一般代表数据缺失):

#5052719630901009999 5
10 85000 1314B 68B-9999-9999-9999

数据头部
标识 站点编号 日期 观察起始时间 观察结束时间 记录数
# 50527 19630901 00 9999 5
数据记录          
Major Level Minor Level 气压(Pa)3-8 气压标识 位势高度(米)10-14 位势高度标识 温度*10(16- 20位) 温度标识 露点下降 风力方向 风速(m/s)
1 0 85000 空格 1314 B 68 B -9999 -9999 -9999

由于MapReduce一行行处理数据,而该数据记录部分依赖于数据头部,MR对数据进行分区时对它们分开的可能性非常大,所以每条数据记录部分必须加上头部的部分信息(根据需要确定),即预处理,对数据预处理的结果可输出到本地,然后再拷贝至HDFS。

在本例中,数据头部只关注<站点编号>、<日期>,数据头部与数据记录形成的新格式如下:

预处理后的数据格式              
505271963090110 85000  1314B   68B-9999-9999-9999                
站点编号 日期 Major Level Minor Level 气压(Pa) 气压标识 位势高度(米)10-14位 位势高度标识 温度*10 温度标识 露点下降 风力方向 风速(m/s)
50527 19630901 1 0 85000 空格 1314 B 68 B -9999 -9999 -9999

即如下面格式的新格式:

592871963090110 85000  1481B  202B-9999  190   20
592871963090110 70000 3139B 142B-9999 180 20
592871963090110 50000 5880B -55B-9999 60 30

三、数据拷贝至HDFS

数据从本地拷贝至HDFS可以通过编码,也可使用eclipse的hadoop插件进行(该插件目前一般需要根据自己的环境编译得到jar放入eclipse的plugins文件夹下,过程稍微繁琐),

当然也可以使用bin/hadoop工具copyFromLocal进行(不过需要先复制到集群中的任意一台机器),本例中把数据存放在HDFS的 /weatherballoon 目录下,以下代码可供参考:

core-site.xml:不同的配置文件方便本地测试和集群切换,在MR程序调试的时候很有用

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://hbase-01:9000</value>
</property>
</configuration>
public class CopyFromLocalMain {

    private static Configuration config = new Configuration();

    public static void main(String[] args) throws Exception {
config.addResource("core-site.xml");
File inputDir = new File("d:/weatherballoon/input/");
String hdfsDir = "/weatherballoon/input/"; if (!inputDir.exists()) {
System.err.println(inputDir.getAbsolutePath() + " directory not exist .");
System.exit(-1);
}
File[] files = inputDir.listFiles();
if (files == null) {
System.err.println(inputDir.getAbsolutePath() + " directory is empty .");
System.exit(-1);
} for (File file : files) {
copyFileToHdfs(file, hdfsDir + file.getName());
}
System.out.println("Copy finished, total: " + files.length);
}
public static void copyFileToHdfs(File local,String dest) throws IOException{
InputStream in = new BufferedInputStream(new FileInputStream(local));
FileSystem fs = FileSystem.get(config);
FSDataOutputStream out = fs.create(new Path(dest));
IOUtils.copyBytes(in, out, 4096, true);
out.close();
}
}

数据拷贝完毕后可访问HDFS的namenode查看状态(默认50070端口),本例状态如下图:

Hadoop - 国内各站点最高温度、气压和风速统计

四、编写MapReduce程序

目前的数据格式已经每行之间无依赖性,首先编辑Mapper部分,该部分用于把站点ID作为key的数据集存入OutputCollector中:

public class MaxTemperatureMapper
extends MapReduceBase implements Mapper<LongWritable, Text, Text, RecordValue>{ public static final int DATA_LENGTH = 49; //预处理后的数据行长度 @Override
public void map(LongWritable key, Text value,
OutputCollector<Text, RecordValue> output, Reporter reporter) throws IOException { //505271963090110 85000 1314B 68B-9999-9999-9999
String line = value.toString();
if (line.length() != DATA_LENGTH) {
System.out.println("------------->Error record : " + line);
return;
} String stationId = line.substring(0, 5);
String date = line.substring(5, 13);
String temp = line.substring(28, 33);
if (!missing(temp)) {
int temperature = Integer.parseInt(temp.trim());
output.collect(new Text(stationId), new RecordValue(date, temperature));
}
} private boolean missing(String temp) {
return temp.equals("-9999");
} }

Mapper中输出的Value值为自定义的类型(即RecordValue),因为需要同时记录日期和温度,如果要自定义类型,则必须实现Writable(如Hadoop自带的LongWritable,IntWritable,Text等)。

实现该接口使得对象能够序列化在不同机器间传输(进程间采用RPC通信,Hadoop采用Avro序列化,其他比较流行的序列化框架有Apache Thrift和Google protocol buffers),

一般建议实现WritableComparable接口,该接口中有个compareTo 方法的实现对于MapReduce来说是比较重要的,用于基于键的中间结果排序。

也可以实现RawComparator ,即可在字节流中排序,而不需要反序列化,减小额外开销。

RecordValue的实现如下:

public class RecordValue implements WritableComparable<RecordValue>{

    private String date;
private int temperature; public RecordValue(){}
public RecordValue(String date, int temperature) {
this.date = date;
this.temperature = temperature;
}
@Override
public void write(DataOutput out) throws IOException {
out.write(date.getBytes());
out.writeInt(temperature);
}
@Override
public void readFields(DataInput in) throws IOException {
byte[] buff = new byte[8];
in.readFully(buff);
date = new String(buff);
temperature = in.readInt();
}
@Override
public int compareTo(RecordValue o) {
if (date.compareTo(o.getDate()) > 0 || temperature > o.getTemperature()) {
return 1;
}
return -1;
}
@Override
public String toString() {
return " -- " + date + "," + temperature;
} //省略setter getter
}

Mapper部分需要做单元测试,成功后接下面编写Reducer部分:

public class MaxTemperatureReducer extends MapReduceBase implements
Reducer<Text, RecordValue, Text, RecordValue> { @Override
public void reduce(Text key, Iterator<RecordValue> values,
OutputCollector<Text, RecordValue> output, Reporter reporter)
throws IOException { int maxValue = Integer.MIN_VALUE;
String date = "00000000";
while (values.hasNext()) {
RecordValue record = values.next();
int temp = record.getTemperature();
if (temp > maxValue) {
maxValue = temp;
date = record.getDate();
}
}
output.collect(key, new RecordValue(date, maxValue));
} }

当Reduce部分单元测试成功后即可编写驱动程序MaxTemperatureDriver,先用本地小数据集进行测试,配置文件切换为本地配置,如:

public static void main(String[] args) throws IOException {

        String inputPath = "file:///d:/weatherballoon/input/*";
String outputPath = "file:///d:/weatherballoon/output"; File out = new File("d:/weatherballoon/output");
if (out.exists()) {
FileUtils.forceDelete(out); //采用apache common io包
} Configuration conf = new Configuration();
conf.addResource("core-site-local.xml"); JobConf job = new JobConf(conf);
job.setJobName("Max Temperature(NCDC)");
job.setMapperClass(MaxTemperatureMapper.class);
job.setReducerClass(MaxTemperatureReducer.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(RecordValue.class); FileInputFormat.addInputPath(job, new Path(inputPath));
FileOutputFormat.setOutputPath(job, new Path(outputPath));
JobClient.runJob(job);
}

运行程序,如果出错则在本地容易查出错误地方,查看输出结构是否如何预期,下面是本例小部分数据集的输出结果:

50527 -- 20040721,358
50557 -- 20100627,342
50603 -- 19730409,440

温度已经乘以10,故对应的结果如下表格:

站点ID 日期 温度(摄氏度)
50527 20040721 35.8
50557 20100627 34.2
50603 19730409 44.0

五、集群运行

测试成功后可切换至集群运行,更改MaxTemperatureDriver的main,如下:

public static void main(String[] args) throws IOException {

        String inputPath = "/weatherballoon/input/";
String outputPath = "/weatherballoon/output"; Configuration conf = new Configuration(); JobConf job = new JobConf(conf);
job.setJobName("Max Temperature(NCDC)");
job.setMapperClass(MaxTemperatureMapper.class);
job.setReducerClass(MaxTemperatureReducer.class);
job.setJarByClass(MaxTemperatureDriver.class); //!important job.setOutputKeyClass(Text.class);
job.setOutputValueClass(RecordValue.class); FileInputFormat.addInputPath(job, new Path(inputPath));
FileOutputFormat.setOutputPath(job, new Path(outputPath));
JobClient.runJob(job);
}

然后程序打包(编写MANIFEST.MF):

Manifest-Version: 1.0
Class-Path: .
Main-Class: org.mike.hadoop.weatherballoon.MaxTemperatureDriver

eclipse->export->jar并选择MANIFEST.MF文件,把jar上传到集群任一节点,执行如下命令:

hadoop jar MaxTemperature.jar

运行如下图:

Hadoop - 国内各站点最高温度、气压和风速统计

成功后即可从HDFS拷贝结果文件至本地查看(或者直接hadoop dfs -cat也可以),本例得到的结果如下(列出小部分):

    -- ,
-- ,
-- ,
-- ,
-- ,
-- ,
-- ,
-- ,
-- ,
-- ,
-- ,

根据NCDN中igra-stations.txt文件得到对应的站点整理后如下:

站点ID 站点名称 日期 最高温度
50527 HAILAR 20040721 35.8
50557 NENJIANG 20100627 34.2
50603 CHIN-BARAG 19730409 44
50745 CHICHIHAR 19990413 38.6
50774 YICHUN 20100624 31.6
50834 TA KO TAI 19920428 42.6
50953 HARBIN 20010604 34.6
51076 ALTAY 19931031 50.6
51133 TA CHENG 19870716 60
51156 HOBOG SAIR 19860309 55.2
51232 BORDER STATION 19800802 22

Finished ..

Hadoop - 国内各站点最高温度、气压和风速统计的更多相关文章

  1. Hadoop的改进实验(中文分词词频统计及英文词频统计)(4&sol;4)

    声明: 1)本文由我bitpeach原创撰写,转载时请注明出处,侵权必究. 2)本小实验工作环境为Windows系统下的百度云(联网),和Ubuntu系统的hadoop1-2-1(自己提前配好).如不 ...

  2. 【Cloud Computing】Hadoop环境安装、基本命令及MapReduce字数统计程序

    [Cloud Computing]Hadoop环境安装.基本命令及MapReduce字数统计程序 1.虚拟机准备 1.1 模板机器配置 1.1.1 主机配置 IP地址:在学校校园网Wifi下连接下 V ...

  3. hadoop自己写的最高温度程序源码

    package com.teset; import java.io.IOException; import java.util.StringTokenizer; import org.apache.h ...

  4. Hadoop国内主要发行版本

    Hadoop主要版本 目前国内使用的不收费的Hadoop版本主要包括以下3个: Apache hadoop Cloudera的CDH Hortonworks版本(Hortonworks Data Pl ...

  5. Linux系统国内镜像站点

    一,更换说明 第一步 备份 如centos, mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup ...

  6. Maven国内下载站点

    鉴于一些原因,从maven*仓库download依赖包时,被各种折磨,下面就简单看下maven setting.xml的一些简单配置 先贴几个国内可用的maven repository连接: htt ...

  7. eclipse使用国内镜像站点安装插件

    把eclipse 4.x的界面改为经典样式 打开eclipse,菜单栏>windows>preference>general>appearance>theme>cl ...

  8. Android studio &amp&semi; SDK的国内有效站点。

    SDK.TOOLS的国内有效镜像节点: mirrors.zzu.edu.cn/android/repository/ 网上的地址只写了mirrors.zzu.edu.cn,有误,需要补齐后面的子目录才 ...

  9. Hadoop第8周练习—Pig部署及统计访问日志例子

    :搭建Pig环境 :计算每个IP点击次数 内容 运行环境说明 1.1     硬软件环境 线程,主频2.2G,6G内存 l  虚拟软件:VMware® Workstation 9.0.0 build- ...

随机推荐

  1. Python自动化 【第十八篇】:JavaScript 正则表达式及Django初识

    本节内容 JavaScript 正则表达式 Django初识 正则表达式 1.定义正则表达式 /.../  用于定义正则表达式 /.../g 表示全局匹配 /.../i 表示不区分大小写 /.../m ...

  2. 玩了一天的Git

    今天的逗比事 Git从学习到使用,也有2个月时间了,一开始也就看看廖雪峰老师的Git教程,跟着做了一遍,感觉非常受用. 遇到一些忘掉的命令,再回去查查也基本都没问题. 但是今天缺遇到了逗比事,回过头来 ...

  3. 【poj2960】 S-Nim

    http://poj.org/problem?id=2960 (题目链接) 题意 经典Nim游戏,只是给出了一个集合S,每次只能取S[i]个石子. Solution ${g(x)=mex\{SG(x- ...

  4. Swift - 使用NSURLSession加载数据、下载、上传文件

    NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的sharedSession()和dataTaskWithR ...

  5. ArcGIS 10&period;1 发布使用ArcEngine自定义的GP服务

    1. 新建立GP模型 在VS2010中新建一个普通的程序及,引入ArcEngine相关的dll.在该DLL中定义一个或多个GP类和一个GP工厂类.GP类要继承IGPFunction2接口,GP工厂类要 ...

  6. 我对RPC的理解

    1.简介 这篇文章将会用最直白的方式介绍RPC,以及实现RPC客户端的Ajax跨域调用的例子. RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过 ...

  7. 1 Spring Cloud Eureka服务治理(下)

    注:此随笔为读书笔记.<Spring Cloud微服务实战> 上篇主要介绍了什么是微服务以及微服务治理的简单实现,如微服务注册中心的实现.微服务注册的实现.微服务的发现和消费的实现.微服务 ...

  8. 账户和联系人 Accounts and Contacts 译

    原文链接: https://crmbook.powerobjects.com/basics/searching-and-navigation/understanding-accounts-and-co ...

  9. protel 99se 全部焊盘和过孔补泪滴,很多都是失败的,对板子有影响吗&quest;补泪滴的作用?

    泪滴     是焊盘与导线或者是导线与导孔之间的滴装连接过度,设置泪滴的目的是在电路板受到巨大外力的冲撞时,避免导线与焊盘或者导线与导孔的接触点断开,另外,设置泪滴也可使PCB电路板显得更加美观.te ...

  10. solr服务器的查询过程

    SolrDispatchFilter的作用 This filter looks at the incoming URL maps them to handlers defined in solrcon ...