使用Hadoop分析气象数据完整版(附带完整代码)

本博客详细介绍了使用Hadoop进行气象数据处理的过程,包括数据下载、清洗、MapReduce编程、Hive数据分析、Sqoop数据导出及可视化展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《分布式》布置了一道小作业,让我花了7天时间学习了Hadoop。。。现在终于可以正式地做这个作业了,记录一下。

1 获取数据

1.1 下载数据

注意:为了不出现横向拖拉,命令里我加了换行,所有命令都是如此。
获取命令:

wget -D --accept-regex=REGEX -P data -r 
	-c ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019/5*

注意:下载可能出现卡顿,直接 ctrl+c 中断,然后再次输入命令即可。

我就下载了下面这么多,共计78429条。
在这里插入图片描述

1.2 数据格式

截取部分数据,格式如下:

2019 01 01 00   -65  -123 10199   345    95     8 -9999 -9999
2019 01 01 01   -62  -115 10213   350    86 -9999 -9999 -9999
2019 01 01 02   -62  -110 10223   343    86 -9999 -9999 -9999
2019 01 01 03   -62  -114 10234   337    77 -9999 -9999 -9999
2019 01 01 04   -62  -118 10242   345    86 -9999 -9999 -9999
2019 01 01 05   -62  -116 10252   331    63 -9999 -9999 -9999
2019 01 01 06   -62  -114 10259   306    38     6 -9999 -9999
2019 01 01 07   -62  -114 10264   281    29 -9999 -9999 -9999
2019 01 01 08   -62  -113 10268   268    39 -9999 -9999 -9999
2019 01 01 09   -59  -116 10271   254    31     3 -9999 -9999
2019 01 01 10   -62  -115 10271   238    24 -9999 -9999 -9999
2019 01 01 11   -80  -122 10269   254    12 -9999 -9999 -9999
2019 01 01 12   -67  -103 10264   322    12     5 -9999 -9999
2019 01 01 13   -62  -100 10261    27    13 -9999 -9999 -9999
2019 01 01 14   -29   -72 10259   230    40 -9999 -9999 -9999
2019 01 01 15   -20   -67 10254   242    49     5 -9999 -9999

字段解释如下:

字段1:位置1-4,长度4:观测年份,四舍五入到最接近
字段2:位置6-7,长度2:观察月,四舍五入到最接近
字段3:位置9-11,长度2:观察日,四舍五入到最接近
字段4:位置12-13,长度2:观察时,四舍五入到最接近
字段5:位置14-19,长度6:空气温度,单位:摄氏度,比例因子:10,缺少值:-9999,
字段6:位置20-24,长度6:露点温度,为了达到饱和,必须在恒定的压力和水蒸气含量下
	冷却给定的空气包的温度。单位:摄氏度,比例因子:10,缺少值:-9999
字段7:Pos 26-31,长度6:海平面压力,相对于平均海平面的气压。单位:公顷,比例因
	子:10,缺少值:-9999
字段8:32-37号位置,长度6:风向。正北角在正北和风向之间以顺时针方向测量的角度。
	单位:角度。比例因子:1,缺少值:-9999。*注:静风风向编码为0。
字段9:38-43位置,长度6:风速,空气通过一个固定点的水平运动速度。单位:米每秒。
	比例因子:10。缺少值:-9999
字段10:位置44-49,长度6:天空状况总覆盖代码,表示被云层或其它遮蔽现象覆盖的整个穹
	顶的一部分的代码。缺少值:-9999
域:
0:无,SKC或CLR
1: 一个okta-1/10或更小但不是零
2: 两个oktas-2/10-3/10,或几个
3: 三个oktas-4/10
4: 四个oktas-5/10,或SCT
5: 五个oktas-6/10
6: 六个oktas-7/10-8/10
7: 七个oktas-9/10或以上,但不是10/10或BKN
8: 八个oktas-10/10,或OVC
9: 天空模糊不清,或云量无法估计
10: 部分遮蔽
11: 稀散
12: 分散的
13: 暗散射
14: 薄断
15: 破碎的
16: 暗断
17: 薄阴
18: 阴天
19: 阴天
字段11:位置50-55,长度6:液体沉淀深度尺寸-持续一小时,在一个小时的积累期内测量
	的液体沉淀的深度。单位:毫米,比例因子:10,缺少值:-9999。*注:痕量降水编码为-1
字段12:位置56-61,长度6:液体沉淀深度尺寸-持续6小时,在六小时的积累期内测量的液
	体沉淀的深度。单位:毫米。比例因子:10。缺少值:-9999。*注:痕量降水编码为-1

字段很多,但是这里我只用前5个字段,任务是统计每日最高温度、最低温度、平均温度,有时间的话顺便计算点儿静态统计值。其余字段应该是类似的,正所谓一通百通。

1.3 合并数据

数据很分散,合并数据:
zcat 2019/*.gz > data.txt

到此数据获取完毕。

2 MapReduce处理数据

2.1 环境配置,启动集群

详情跳转到 : 大数据学习系列:Hadoop3.0苦命学习(一),本文不再赘述。

2.2 上传到HDFS

hdfs dfs -mkdir -p /usr/hadoop/in
hdfs dfs -ls /usr/hadoop/
hdfs dfs -put data.txt /usr/hadoop/in/

执行截图:
在这里插入图片描述
去控制台查看一下是否成功:

在这里插入图片描述

2.2 编写MapReduce代码

2.2.1 TemperatureMapper

public class TemperatureMapper extends Mapper<LongWritable, Text, 
		Text, LongWritable> {

    private static final long MISSING = -9999;

    @Override
    protected void map(LongWritable key, Text value, Context context) 
    		throws IOException, InterruptedException {
        String line = value.toString();
        Iterable<String> split = Splitter.on(" ").omitEmptyStrings().split(line);
        ArrayList<String> arrayList = new ArrayList<>(16);
        for (String s : split) {
            arrayList.add(s);
        }
        // 过滤掉字段不足的数据
        if (arrayList.size() >= 5) {
            String month = arrayList.get(1);
            String day = arrayList.get(2);
            long temperature = Long.parseLong(arrayList.get(4));
            // 过滤掉温度不存在的数据
            if (Math.abs(temperature - MISSING) > 0.0001) {
                context.write(new Text(month + "/" + day), 
                		new LongWritable((temperature)));
            }
        }
    }

}

主要是原数据进行了清洗,过滤了一些不合格的数据。

2.2.2 TemperatureReducer

public class TemperatureReducer extends Reducer<Text, LongWritable, 
		Text, Temperature> {
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, 
    		Context context) throws IOException, InterruptedException {
        long maxTemperature = Long.MIN_VALUE;
        long minTemperature = Long.MAX_VALUE;
        double avgTemperature = 0.0;
        long temp;
        int count = 0;
        if (values!=null) {
            for (LongWritable value: values) {
                temp = value.get();
                maxTemperature = Math.max(temp, maxTemperature);
                minTemperature = Math.min(temp, minTemperature);
                avgTemperature += temp;
                count++;
            }
            Temperature temperature = new Temperature(maxTemperature, 
            		minTemperature, avgTemperature/count);

            context.write(key, temperature);
        }

    }
}

计算出每日温度的最大值、最小值和平均值,并放入Temperature对象中。

2.2.3 JobMain

public class JobMain extends Configured implements Tool {
    @Override
    public int run(String[] strings) throws Exception {
        // 创建一个任务对象
        Job job = Job.getInstance(super.getConf(), "mapreduce_temperature");

        // 打包放在集群运行时,需要做一个配置
        job.setJarByClass(JobMain.class);

        // 第一步:设置读取文件的类:K1和V1
        job.setInputFormatClass(TextInputFormat.class);
        TextInputFormat.addInputPath(job, 
        	new Path("hdfs://node01:8020/usr/hadoop/in"));

        // 第二步:设置Mapper类
        job.setMapperClass(TemperatureMapper.class);
        // 设置Map阶段的输出类型:k2和v2的类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        // 第三、四、五、六步采用默认方式(分区,排序,规约,分组)

        // 第七步:设置Reducer类
        job.setReducerClass(TemperatureReducer.class);
        // 设置Reduce阶段的输出类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Temperature.class);


        // 第八步:设置输出类
        job.setOutputFormatClass(TextOutputFormat.class);
        // 设置输出路径
        TextOutputFormat.setOutputPath(job, 
        	new Path("hdfs://node01:8020/usr/hadoop/temperature"));

        boolean b = job.waitForCompletion(true);

        return b?0:1;
    }

    public static void main(String[] args) throws Exception {
        Configuration configuration = new Configuration();
        // 启动一个任务
        ToolRunner.run(configuration, new JobMain(), args);
    }

}

2.3 执行

2.3.1 打包、上传

老套路,不说了。

2.3.2 运行

hadoop jar temperature_test-1.0-SNAPSHOT.jar cn.sky.hadoop.JobMain
执行结果:
在这里插入图片描述
在这里看一眼数据:
在这里插入图片描述
嗯,还行。

3 导入数据到Hive

Hive详情过程,请参考:大数据学习系列:Hadoop3.0苦命学习(五)

有个问题,若直接从HDFS导入数据到Hive,HDFS上的数据会丢失。

所以我将数据下载下来,重命名为 temperature_data ,并上传到 node03
在这里插入图片描述
数据有了,开始创建Hive表:

 create external table temperature (t_date string, t_max double, 
 	t_min double, t_avg double) row format delimited fields terminated by '\t';

加载数据到hive:

load data local inpath '/export/services/temperature_data' overwrite 
	into table temperature;

查前面5条数据,看一眼:

select * from temperature limit 5;

在这里插入图片描述

4 Hive数据分析

弄得简单,就查几个静态数据吧。

  1. 查询2019全年平均温度
    select avg(t_avg) from temperature;

哇,太慢了,查了25秒,最终结果是3.46(因为数据是被放大了10倍)左右
在这里插入图片描述

  1. 查询2019全年高于平均温度的天数
    select count(1) from temperature where t_avg > 34.6;
    答案是:196天,很显然低于平均气温的天数是169天。

在这里插入图片描述
好了,差不多就行了。

5 使用Sqoop导入数据到Mysql

Sqoop详情过程,请参考:大数据学习系列:Hadoop3.0苦命学习(七)

5.1 Mysql创建数据库

CREATE TABLE `temperature` (
  `Tem_Date` varchar(10) NOT NULL,
  `Tem_Max` double DEFAULT NULL,
  `Tem_Min` double DEFAULT NULL,
  `Tem_Avg` double DEFAULT NULL,
  PRIMARY KEY (`Tem_Date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

5.2 开始导入

bin/sqoop export --connect jdbc:mysql://192.168.0.102:3306/userdb 
	--username root --password 123456 --table temperature 
	--export-dir /usr/hadoop/temperature --input-fields-terminated-by "\t"

经过半分钟的等待,就可以在mysql中查到数据了,见下图:
在这里插入图片描述
不错,数据很好。

6 展示数据

这里前端使用echart,jsp,后端使用Spring、SpringMVC、Mybatis。

代码较多,展示主要的。

6.1 前端代码

在这里插入图片描述
主要是这一段,使用Ajax向后台请求数据,然后将数据丢进eChart中。

6.2 后端代码

controller层

@Autowired
    private TemperatureService tempService;
    @RequestMapping("/getTemperature.action")
    @ResponseBody
    public TemperatureReturnPojo getTemperature(){
        TemperatureReturnPojo temperaturePojo =  tempService.getAllTemperature();
        System.out.println(temperaturePojo);
        return temperaturePojo;
    }

Service层

public interface TemperatureService {
    TemperatureReturnPojo getAllTemperature();
}

Service实现类

@Service
public class TemperatureServiceImpl implements TemperatureService {
    @Autowired
    private TemperatureMapper temperatureMapper;
    @Override
    public TemperatureReturnPojo getAllTemperature() {
        TemperatureReturnPojo temperatureReturnPojo 
        	= new TemperatureReturnPojo();

        ArrayList<String> dates = new ArrayList<>();
        ArrayList<String> maxs = new ArrayList<>();
        ArrayList<String> mins = new ArrayList<>();
        ArrayList<String> avgs = new ArrayList<>();
        DecimalFormat df = new DecimalFormat("#.00");

        List<TemperaturePojo> allTemperature 
        	= temperatureMapper.getAllTemperature();
        for (TemperaturePojo pojo : allTemperature) {
            dates.add(pojo.getTem_Date());
            maxs.add(df.format(pojo.getTem_Max()/10.0));
            mins.add(df.format(pojo.getTem_Min()/10.0));
            avgs.add(df.format(pojo.getTem_Avg()/10.0));
        }
        temperatureReturnPojo.setTem_Dates(dates);
        temperatureReturnPojo.setTem_Maxs(maxs);
        temperatureReturnPojo.setTem_Mins(mins);
        temperatureReturnPojo.setTem_Avgs(avgs);

        return temperatureReturnPojo;
    }
}

实体类

public class TemperaturePojo {
    private String Tem_Date;
    private Double Tem_Max;
    private Double Tem_Min;
    private Double Tem_Avg;
	
	// 省略Get()、Set()、ToString()方法    
}

public class TemperatureReturnPojo {
    private List<String> Tem_Dates;
    private List<String> Tem_Maxs;
    private List<String> Tem_Mins;
    private List<String> Tem_Avgs;
 	// 省略Get()、Set()、ToString()方法    
}   

Mapper

public interface TemperatureMapper {
    List<TemperaturePojo> getAllTemperature();
}
<mapper namespace="cn.itcast.weblog.mapper.TemperatureMapper" >
    <select id="getAllTemperature"   
    		resultType="cn.itcast.weblog.pojo.TemperaturePojo">
        select * from temperature;
    </select>

</mapper>

运行结果如下:
在这里插入图片描述
在这里插入图片描述
流程完成,撒花~~~

代码:完整代码下载


csdn资源下载从1积分涨到了50积分,可怕。

因此我又把放到了github 完整代码下载


2022年12月15日更新:很多同学在问数据在哪在哪,其实在1.1节已经说过了,现在说详细点儿。

  1. linux命令行输入:

wget -D --accept-regex=REGEX -P data -r -c ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019/5*

就会看到下面的提示,表示正在下载了。
在这里插入图片描述

  1. 下载一会儿后,当前目录下就会有 data/ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019 ,进入这个目录,你可以看到1.1节的数据了。

在这里插入图片描述

<think>好的,用户需要关于使用RNN进行股票价格预测的代码示例和数据收集方法。首先,我得回忆一下之前提供的引用内容,特别是引用3提到的步骤:数据收集、预处理、模型设计、训练和评估。用户可能已经对这些步骤有基本了解,现在需要具体的代码和收集数据的方法。 数据收集部分,用户可能需要知道从哪里获取股票数据。常见的数据源包括Yahoo Finance、Alpha Vantage、Quandl等。这些平台通常提供API,比如使用Python的yfinance库可以方便地下载数据。需要详细说明如何安装和使用这些库,比如安装命令和示例代码。另外,数据字段如开盘价、收盘价、成交量等也需要提及,确保用户了解哪些数据是必要的。 然后是数据预处理,这部分可能涉及数据清洗(处理缺失值)、归一化(使用MinMaxScaler)、以及构造时间序列数据。例如,如何将数据转换为适合RNN输入的序列格式,比如用过去60天的数据预测下一天的价格。代码示例需要展示如何用Pandas处理数据,用scikit-learn进行归一化,以及如何生成训练集和测试集。 接下来是模型构建部分。用户需要RNN的代码示例,可能需要选择Keras或PyTorch框架。考虑到用户可能更熟悉Keras,使用Sequential模型构建一个简单的RNN结构,包括SimpleRNN层、Dense层。需要解释每个层的作用,比如输入形状、激活函数等。同时,要提到LSTM和GRU作为更高级的选项,供用户进一步优化。 训练模型部分,需要展示编译模型(选择优化器和损失函数)和训练过程(fit方法),并强调验证集的使用和防止过拟合的方法,比如早停法。这里可以给出回调函数的示例代码,但根据用户需求,可能暂时不需要太复杂的设置,保持代码简洁。 预测和评估部分,需要展示如何逆归一化预测结果,计算均方误差,并用图表展示真实值与预测值的对比。这部分的可视化很重要,用户可能希望直观地看到模型效果。 最后,相关问题部分需要考虑用户可能的后续问题,比如特征工程、模型调参、处理过拟合、实时数据预测,以及与其他模型的比较。这些问题能帮助用户深入学习和解决问题。 需要检查代码是否符合规范,比如使用正确的缩进,库的导入是否正确,数据处理的步骤是否清晰。同时,确保引用了正确的来源,比如引用3提到的数据预处理和模型设计步骤,引用4关于RNN的结构说明。避免使用用户不可见的指令,保持回答结构清晰,分步骤讲解,代码示例正确可运行。</think>### RNN股票价格预测代码及数据收集方法分步教程 一、数据收集方法 1. **数据源选择**: - Yahoo Finance:使用$yfinance$库(Python) - Alpha Vantage:提供免费API(需注册API Key) - 东方财富/新浪财经(中文数据源) 2. **数据下载代码示例**: ```python import yfinance as yf # 下载苹果公司股票数据(示例) data = yf.download('AAPL', start='2010-01-01', end='2023-12-31', interval='1d') print(data.head()) # 显示包含开盘价、最高价、最低价、收盘价、成交量的数据[^3] ``` 二、数据预处理流程 1. **数据清洗**: ```python # 处理缺失值 data.fillna(method='ffill', inplace=True) ``` 2. **特征归一化**: ```python from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler(feature_range=(0,1)) scaled_data = scaler.fit_transform(data['Close'].values.reshape(-1,1)) ``` 3. **序列构造**: ```python def create_sequences(data, seq_length=60): X, y = [], [] for i in range(len(data)-seq_length-1): X.append(data[i:(i+seq_length)]) y.append(data[i+seq_length]) return np.array(X), np.array(y) X, y = create_sequences(scaled_data) ``` 三、RNN模型构建(Keras实现) ```python from keras.models import Sequential from keras.layers import SimpleRNN, Dense model = Sequential([ SimpleRNN(50, return_sequences=True, input_shape=(X.shape[1], 1)), SimpleRNN(50), Dense(1) ]) model.compile(optimizer='adam', loss='mean_squared_error') ``` 四、模型训练与验证 ```python history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2, verbose=1) ``` 五、预测与结果可视化 ```python # 逆归一化处理 predictions = scaler.inverse_transform(predicted_stock_price) actual = scaler.inverse_transform(y_test.reshape(-1,1)) # 绘制对比图 plt.plot(actual, color='red', label='Real Stock Price') plt.plot(predictions, color='blue', label='Predicted Stock Price') plt.title('Stock Price Prediction') plt.xlabel('Time') plt.ylabel('Price') plt.legend() plt.show() ```
评论 112
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值