前哨站/第10章 天气数据分析实战
第10章 天气数据分析实战

第10章 天气数据分析实战

把前面九章串成一个项目:采集天气数据 → Sqoop 入库 → 清洗去重分区 → 三类分析。

综合项目全流程Sqoop+Hive

本章学习目标

  • 能说明案例背景、目的与整体流程
  • 能完成数据采集并用 Sqoop 将 MySQL 数据导入 Hive
  • 能完成缺失值处理、格式化、去重与分区
  • 能写出月气温、晴天天数、霾天气三类分析 SQL

本章导览

核心内容

10.1

案例简介

数据来源为天气网站的公开数据,包含日期、城市、最高温、最低温、天气、风向、风力等字段。目标是把"脏数据"变成可分析的指标表。

项目整体流程(教材 10.1.3)
阶段任务产出
数据采集分析页面结构、抓取数据、存入 MySQL原始数据表
数据预处理缺失值处理、格式化、去重、分区清洗后的明细表
数据分析月气温、晴天天数、霾天气分析指标结果
10.2

数据采集

SHELL
# 1) 建 MySQL 接收表(字段与页面一致,先全用字符串接住)
CREATE TABLE nev.weather (
  id INT PRIMARY KEY AUTO_INCREMENT,
  city VARCHAR(20), wdate VARCHAR(20),
  high VARCHAR(10), low VARCHAR(10),
  weather VARCHAR(30), wind VARCHAR(30), power VARCHAR(20)
);

# 2) 采集后(脚本/Python),用 Sqoop 导入 Hive
sqoop import \
  --connect jdbc:mysql://hadoop1:3306/nev --username root --password 123456 \
  --table weather --hive-import --hive-database ods --hive-table weather_ods \
  --fields-terminated-by '\t' -m 1
10.3

数据预处理

教材把预处理拆成四步:缺失值处理、数据格式化、数据去重、数据分区——这四步是离线分析项目的标准动作。

10.3.1

缺失值处理与格式化

SHELL
-- 缺失值:补默认值或排除
SELECT nvl(high, '0') AS high, nvl(weather, '未知') AS weather FROM weather_ods;

-- 格式化:"3℃" → 3;"2025年07月01日" → 2025-07-01
SELECT cast(regexp_replace(high, '[^0-9-]', '') AS INT) AS high_num,
       date_format(to_date(wdate, 'yyyy年MM月dd日'), 'yyyy-MM-dd') AS dt
FROM weather_ods;
10.3.3

数据去重与分区

SHELL
-- 去重:按城市+日期保留一条(row_number 或 distinct)
INSERT OVERWRITE TABLE dwd.weather_clean PARTITION (y, m)
SELECT city, dt, high_num, low_num, weather,
       year(dt) AS y, month(dt) AS m
FROM (
  SELECT *, row_number() OVER (PARTITION BY city, dt ORDER BY id DESC) rn
  FROM tmp_weather_parsed
) t WHERE rn = 1;

💡 先按分区字段(年月)分区,后续所有分析都能命中分区裁剪,扫描量大幅下降。

10.4

数据分析

教材给出三类分析,正好覆盖"聚合统计、条件统计、文本匹配"三种典型写法。

10.4.1

月气温分析

SHELL
SELECT m, round(avg(high_num), 1) AS avg_high,
       max(high_num) AS max_high, min(low_num) AS min_low
FROM dwd.weather_clean
WHERE y = '2025'
GROUP BY m ORDER BY m;
10.4.2

各城市每月晴天天数统计

SHELL
SELECT city, m, count(*) AS sunny_days
FROM dwd.weather_clean
WHERE y = '2025' AND weather LIKE '%晴%'
GROUP BY city, m
ORDER BY city, m;
10.4.3

北京市霾天气的初步分析

SHELL
SELECT m, count(*) AS haze_days,
       round(count(*) * 100 / 30, 1) AS haze_rate
FROM dwd.weather_clean
WHERE city = '北京' AND y = '2025' AND (weather LIKE '%霾%' OR weather LIKE '%雾%')
GROUP BY m ORDER BY m;
这类分析的关键是口径:什么算霾天(只算"霾"还是含"雾")、分母取当月天数还是有效记录数——口径不同结论会差很多,写进报告时要注明。

本章小结

本章是一次完整的小型离线分析项目:先理解背景与流程,再完成数据采集与 Sqoop 入库,接着按"缺失值处理 → 格式化 → 去重 → 分区"四步清洗进 DWD 层,最后完成月气温、晴天天数、霾天气三类分析。这套流程可以直接套用到任何日志分析场景。

思考与练习 先自己做,再点开答案

01

为什么预处理阶段要先去重再分区?

查看参考答案

分区是按年月切目录,若先去重后分区,数据量更小、目录更干净;若先分区再去重,需要在每个分区内单独去重,容易漏掉跨分区的重复(例如同一城市同一天在不同分区)。

02

数据分区对后续分析有什么好处?

查看参考答案

分区裁剪:带年/月条件的查询只扫描对应目录,扫描量可降低一到两个数量级;同时便于按天/月增量重跑与归档。

03

"霾天气分析"的口径为什么要写清楚?

查看参考答案

不同口径(是否含雾、分母是自然日还是有效记录)会得出不同占比,结论可能完全相反。数据分析报告必须注明口径,否则无法复现与对比。