头歌 MapReduce综合应用案例 — 气象数据清洗

任务描述
本关任务:对数据按照一定规则进行清洗。

编程要求
根据提示,在右侧编辑器补充代码,对数据按照一定规则进行清洗。

数据说明如下:a.txt;

数据切分方式:一个或多个空格;

数据所在位置:/user/test/input/a.txt;

2005 01 01 16    -6   -28 10157   260    31     8     0 -9999

2005    01    01    16    -6    -28    10157    260    31    8    0    -9999
年    月    日    小时    温度    湿度    气压    风向    风速    天气情况    1h降雨量    6h降雨量
sky.txt;

数据切分方式:逗号;

数据所在位置:data/sky.txt或者/user/test/input/sky.txt。

1,积云

1    积云
天气情况    cumulus
清洗规则:

将分隔符转化为逗号;
清除不合法数据:字段长度不足,风向不在[0,360]的,风速为负的,气压为负的,天气情况不在[0,10],湿度不在[0,100],温度不在[-40,50]的数据;
将a.txt与sky.txt的数据以天气情况进行join操作,把天气情况变为其对应的云属;
对进入同一个分区的数据排序; 排序规则: (1)同年同月同天为key; (2)按每日温度升序; (3)若温度相同则按风速升序; (4)风速相同则按压强降序。
设置数据来源文件路径及清洗后的数据存储路径: 数据来源路径为: /user/test/input/a.txt (HDFS); 清洗后的数据存放于:/user/test/output (HDFS)。
数据清洗后如下:

2005,01,01,16,-6,-28,10157,260,31,卷云,0,-9999

测试说明
平台会对你编写的代码进行测试:

评测之前先在命令行启动hadoop:start-all.sh;

Weather:封装对象;
WeatherMap:map端操作;
WeatherReduce:reduce端操作;
Auto:自定义分区;
WeatherTest:测试结果类。

具体本关的预期输出请查看右侧测试集。

因为大数据实训消耗资源较大,且map/reduce运行比较耗时,所以评测时间较长,大概在60秒左右,请耐心等待。

开始你的任务吧,祝你成功!

package com;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;

/**封装对象*/
public class Weather implements WritableComparable<Weather> {
    //年
    private String year;
    //月
    private String month;
    //日
    private String day;
    //小时
    private String hour;
    //温度
    private int temperature;
    //湿度
    private String dew;
    //气压/压强
    private int pressure;
    //风向
    private String wind_direction;
    //风速
    private int wind_speed;
    //天气情况
    private String sky_condition;
    //1小时降雨量
    private String rain_1h;
    //6小时降雨量
    private String rain_6h;

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getMonth() {
        return month;
    }

    public void setMonth(String month) {
        this.month = month;
    }

    public String getDay() {
        return day;
    }

    public void setDay(String day) {
        this.day = day;
    }

    public String getHour() {
        return hour;
    }

    public void setHour(String hour) {
        this.hour = hour;
    }

    public int getTemperature() {
        return temperature;
    }

    public void setTemperature(int temperature) {
        this.temperature = temperature;
    }

    public String getDew() {
        return dew;
    }

    public void setDew(String dew) {
        this.dew = dew;
    }

    public int getPressure() {
        return pressure;
    }

    public void setPressure(int pressure) {
        this.pressure = pressure;
    }

    public String getWind_direction() {
        return wind_direction;
    }

    public void setWind_direction(String wind_direction) {
        this.wind_direction = wind_direction;
    }

    public int getWind_speed() {
        return wind_speed;
    }

    public void setWind_speed(int wind_speed) {
        this.wind_speed = wind_speed;
    }

    public String getSky_condition() {
        return sky_condition;
    }

    public void setSky_condition(String sky_condition) {
        this.sky_condition = sky_condition;
    }

    public String getRain_1h() {
        return rain_1h;
    }

    public void setRain_1h(String rain_1h) {
        this.rain_1h = rain_1h;
    }

    public String getRain_6h() {
        return rain_6h;
    }

    public void setRain_6h(String rain_6h) {
        this.rain_6h = rain_6h;
    }

    @Override
    public String toString() {
        return year + "," + month + "," + day + "," + hour + "," + temperature + "," + dew + "," + pressure + ","
                + wind_direction + "," + wind_speed + "," + sky_condition + "," + rain_1h + "," + rain_6h;
    }

    public Weather() {
    }

    public Weather(String year, String month, String day, String hour, int temperature, String dew, int pressure,
            String wind_direction, int wind_speed, String sky_condition, String rain_1h, String rain_6h) {
        this.year = year;
        this.month = month;
        this.day = day;
        this.hour = hour;
        this.temperature = temperature;
        this.dew = dew;
        this.pressure = pressure;
        this.wind_direction = wind_direction;
        this.wind_speed = wind_speed;
        this.sky_condition = sky_condition;
        this.rain_1h = rain_1h;
        this.rain_6h = rain_6h;
    }

    public void readFields(DataInput in) throws IOException {
        year = in.readUTF();
        month = in.readUTF();
        day = in.readUTF();
        hour = in.readUTF();
        temperature = in.readInt();
        dew = in.readUTF();
        pressure = in.readInt();
        wind_direction = in.readUTF();
        wind_speed = in.readInt();
        sky_condition = in.readUTF();
        rain_1h = in.readUTF();
        rain_6h = in.readUTF();
    }

    public void write(DataOutput out) throws IOException {
        out.writeUTF(year);
        out.writeUTF(month);
        out.writeUTF(day);
        out.writeUTF(hour);
        out.writeInt(temperature);
        out.writeUTF(dew);
        out.writeInt(pressure);
        out.writeUTF(wind_direction);
        out.writeInt(wind_speed);
        out.writeUTF(sky_condition);
        out.writeUTF(rain_1h);
        out.writeUTF(rain_6h);
    }

    public int compareTo(Weather o) {
        // 首先比较年份
        int tmp = this.year.compareTo(o.year);
        if (tmp != 0) {
            return tmp;
        }
        
        // 年份相同,比较月份
        tmp = this.month.compareTo(o.month);
        if (tmp != 0) {
            return tmp;
        }
        
        // 月份相同,比较日期
        tmp = this.day.compareTo(o.day);
        if (tmp != 0) {
            return tmp;
        }
        
        // 年月日都相同,比较温度(升序)
        tmp = Integer.compare(this.temperature, o.temperature);
        if (tmp != 0) {
            return tmp;
        }
        
        // 温度相同,比较风速(升序)
        tmp = Integer.compare(this.wind_speed, o.wind_speed);
        if (tmp != 0) {
            return tmp;
        }
        
        // 风速相同,比较压强(降序)
        return Integer.compare(o.pressure, this.pressure);
    }
}
创作不易,如果能解决您的问题,麻烦您点赞、收藏+关注,一键三连!!!
### MapReduce气象数据清洗中的综合应用案例 #### 案例概述 通过MapReduce技术实现气象数据的高效清洗是一项常见的大数据处理任务。在此过程中,主要目标是对原始气象数据进行预处理,使其满足特定的质量标准并便于后续分析[^1]。 #### 数据清洗规则 为了确保数据质量,在此项目中关涉到的具体清洗规则如下: - **分隔符转换**:将源文件中的任意分隔符统一替换为逗号以便于解析和进一步处理。 - **非法数据剔除**:移除不符合逻辑范围的数据项,具体包括但不限于以下条件之一的情况: - 风向数值超出合理区间[0,360]; - 风速或气压存在负值; - 天气状况编码未处于指定集合[0,10]之内; - 湿度百分比偏离正常范围[0,100]; - 温度记录低于绝对最低温(-40℃)或者高于极端高温(50℃)。 #### 文件Join操作 完成初步筛选之后,需执行一次基于天气状态码的连接(join)运算。即将`a.txt`文档内的基础观测资料与描述天空覆盖程度(`cloud cover`)详情的辅助表`sky.txt`相结合,从而把抽象化的天气代号映射成直观易懂的文字表述形式——即所谓的“云属”。 #### 排序策略制定 针对经过上述步骤整理出来的合格条目集,还需按照既定顺序重新排列组合起来,形成最终输出版本。具体的排序依据设定如下优先级次序依次递减的原则来进行安排: 1. 年份、月份以及日期完全一致者视为同一组键(key),以此作为首要分类标志; 2. 对应每组内部成员再依其当日实测气温高低实施升序编列; 3. 若遇到两笔或多笔记录拥有相等体温读数,则继续考察它们各自的风力强度大小关系,并采取从小至大方式排队; 4. 当前述三项指标均无法区分先后位置时,则最后参照大气压力水平做反方向调整(由高往低),达成彻底区分开来的目的。 #### 路径配置说明 整个作业流程涉及两个重要目录地址定义: - 输入端指向存放待加工素材的位置 `/user/test/input/a.txt` (位于HDFS分布式文件系统之上); - 输出成果则会被保存进另一处专门设立用于接收结果的地方 `/user/test/output`(同样处在HDFS环境当中). ```python from operator import itemgetter def mapper(line): fields = line.strip().split(',') try: year, month, day = map(int, fields[:3]) temperature = float(fields[7]) wind_speed = float(fields[8]) pressure = int(fields[9]) humidity = int(fields[10]) weather_code = int(fields[11]) if not all([ 0 <= wind_direction <= 360, wind_speed >= 0, pressure >= 0, 0 <= weather_code <= 10, 0 <= humidity <= 100, -40 <= temperature <= 50]): return None cloud_cover = sky_lookup.get(weather_code,"Unknown") key = f"{year}{month:0>2d}{day:0>2d}" value_tuple = ( round(temperature,2), round(wind_speed,2), pressure, ','.join(map(str,[year,month,day]+fields[3:] + [cloud_cover])) ) yield key,value_tuple except Exception as e: pass def reducer(grouped_data): sorted_group = sorted( grouped_data,key=itemgetter(0,1,-1),reverse=[False,False,True] ) for _,values in sorted_group: yield values[-1] if __name__ == "__main__": from hadoop.io import Text from hadoop.mapreduce.lib.input import TextInputFormat from hadoop.conf import Configuration conf=Configuration() job = Job(conf) job.setJarByClass(MapReduceExample.class) job.setInputFormatClass(TextInputFormat) job.setOutputKeyClass(Text) job.setOutputValueClass(Text) input_path="/user/test/input/a.txt" output_path="/user/test/output" job.waitForCompletion(True) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值