文章目录
赛事背景数据说明数据处理导入数据并查看基本情况分析数据数据清洗特征工程
构建模型建立训练数据集和测试数据集模型构建
赛事背景
据报道,阿联酋多地已经持续49℃的高温,国内多地也持续40℃的高温。说起来对今年7、8月份的印象,相信很多人会说一个字:热。身处室外像置身于桑拿房里,今年这条命是空调给的。
气候变化对人们的生产生活与环境有着重要的影响,温度预测是当今世界最重要和最具挑战性的任务之一。准确预估某一地区的温度及气候变化,及时反馈给用户是众多天气预测软件的核心业务,也是一大难点。
面对如此头疼的问题,某平台将部分地区气象相关数据开放,诚邀大家帮助他们建立气温预测模型来预测未来气温(敏感信息已脱敏)。
数据说明
赛题数据由训练集和测试集组成,总数据量超过百万,包含14个特征字段(部分字段信息已脱敏):
训练数据包含2016年1月1日到2021年11月30日各站点的气象相关数据;
测试集为各站点2021年12月份数据。
特征字段降水量、气温、湿球空气温度、露点空气温度、蒸气压、相对湿度、平均海平面压力、平均每小时风速、主要每小时风向、地区、站号、年、月、日
数据处理
导入数据并查看基本情况
import pandas as pd
# 导入训练数据集及测试数据集
train_data = pd.read_csv('F:/DocumentFile/data/地区温度预测挑战赛公开数据/train.csv')
test_data = pd.read_csv('F:/DocumentFile/data/地区温度预测挑战赛公开数据/test.csv')
print("训练数据集:", train_data.shape, "测试数据集", test_data.shape)
![](https://img-blog.csdnimg.cn/1df943a69cb248979ba8751735d83eed.jpeg#pic_center)
# 查看训练数据
train_data.head()
![在这里插入图片描述](https://img-blog.csdnimg.cn/da07d395526c418fa932e12f65884cac.jpeg#pic_center)
# 浏览数据的基本信息
train_data.info()
![在这里插入图片描述](https://img-blog.csdnimg.cn/2c22942dbb2242bc914dbb9a9d680d13.jpeg#pic_center)
分析数据
import matplotlib.pyplot as plt
import numpy as np
# 查看降水量与温度的关系
Precipitation_Temperature = train_data[['降水量', '气温']]
plt.scatter(Precipitation_Temperature['降水量'], Precipitation_Temperature['气温'])
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.xlabel('降水量')
plt.ylabel('气温')
plt.show()
单从降水量和气温关系来看,无法准确知道其相应关系,因为在无降水量时,温度的跨度太大,还需要结合其他特征来进行分析
# 查看湿球空气温度与温度的关系
Wet_bulb_Temperature = train_data[['湿球空气温度', '气温']]
plt.scatter(Wet_bulb_Temperature['湿球空气温度'], Wet_bulb_Temperature['气温'])
plt.xlabel('湿球空气温度')
plt.ylabel('气温')
plt.show()
可以看出当湿球空气温度>-10时,与气温成正比的线性关系
# 查看露点空气温度与温度的关系
Dew_Point_Temperature = train_data[['露点空气温度', '气温']]
plt.scatter(Dew_Point_Temperature['露点空气温度'], Dew_Point_Temperature['气温'])
plt.xlabel('露点空气温度')
plt.ylabel('气温')
plt.show()
可以看出露点空气温度和气温成正比的线性关系
# 查看蒸气压与温度的关系
Vapor_Pressure_Temperature = train_data[['蒸气压', '气温']]
plt.scatter(Vapor_Pressure_Temperature['蒸气压'], Vapor_Pressure_Temperature['气温'])
plt.xlabel('蒸气压')
plt.ylabel('气温')
plt.show()
可以看出蒸气压和气温成正比的线性关系
# 查看相对湿度与温度的关系
Relative_Humidity_Temperature = train_data[['相对湿度', '气温']]
plt.scatter(Relative_Humidity_Temperature['相对湿度'], Relative_Humidity_Temperature['气温'])
plt.xlabel('相对湿度')
plt.ylabel('气温')
plt.show()
可以看出相对湿度和气温成反比的线性关系
# 查看平均画面压力与温度的关系
Mean_Sea_Pressure_Temperature = train_data[['平均海平面压力', '气温']]
plt.scatter(Mean_Sea_Pressure_Temperature['平均海平面压力'], Mean_Sea_Pressure_Temperature['气温'])
plt.xlabel('平均海平面压力')
plt.ylabel('气温')
plt.show()
可以看出平均海平面压力与气温的关系很像正态分布,在1010-1030达到峰值
# 查看平均每小时风速及主要每小时风向和气温的关系
Mean_Wind_Speed_Temperature = train_data[['平均每小时风速', '气温']]
Main_Wind_Direction_Temperature = train_data[['主要每小时风向', '气温']]
fig1 = plt.figure()
ax1 = fig1.add_subplot(1, 2, 1)
plt.scatter(Mean_Wind_Speed_Temperature['平均每小时风速'], Mean_Wind_Speed_Temperature['气温'])
plt.xlabel('平均每小时风速')
plt.ylabel('气温')
ax2 = fig1.add_subplot(1, 2, 2)
plt.scatter(Main_Wind_Direction_Temperature['主要每小时风向'], Main_Wind_Direction_Temperature['气温'])
plt.xlabel('主要每小时风向')
plt.ylabel('气温')
plt.show()
平均每小时风速和气温的关系和降水量与气温的关系颇为相似,单看风向没找到什么关系,应该还要结合其他特征
# 查看地区和站号与气温的关系
Region_Temperature = train_data[['地区', '气温']]
Station_NUN_Temperature = train_data[['站号', '气温']]
fig1 = plt.figure()
ax1 = fig1.add_subplot(1, 2, 1)
plt.scatter(Region_Temperature['地区'], Region_Temperature['气温'])
plt.xlabel('地区')
plt.ylabel('气温')
ax2 = fig1.add_subplot(1, 2, 2)
plt.scatter(Station_NUN_Temperature['站号'], Station_NUN_Temperature['气温'])
plt.xlabel('站号')
plt.ylabel('气温')
plt.show()
数据倾向于均匀分布
# 先简单查看年月与气温的关系
Year_Month_Temperature = train_data.groupby(['年', '月'], as_index=False)['气温'].apply(np.mean)
fig1 = plt.figure(figsize=(20, 15))
for i in range(5):
ax1 = fig1.add_subplot(2, 3, i+1)
month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
plt.plot(month, Year_Month_Temperature[Year_Month_Temperature['年'] == 2016+i]['气温'])
plt.xticks([x+1 for x in range(12)])
plt.xlabel("月份")
plt.ylabel("月平均气温")
plt.title(str(2016+i)+"年")
ax2 = fig1.add_subplot(2, 3, 6)
plt.plot(range(11), Year_Month_Temperature[Year_Month_Temperature['年'] == 2021]['气温'])
plt.xticks([x+1 for x in range(12)])
plt.xlabel("月份")
plt.ylabel("月平均气温")
plt.title(str(2021)+"年")
plt.show()
此处显示不同年份每个月的平均气温,可以明显看出没奶奶的气温符合正态分布,6-8月达到峰值
数据清洗
由之前info方法得知我们需要预测的气温属性在训练集中存在缺失值,于是打算在合并测试集之前先进行缺失值填充
# 在合并数据前先将train数据集中缺失的(气温)属性用均值填充
train_data['气温'] = train_data['气温'].fillna(train_data['气温'].mean())
接下来为了方便数据的清洗,需要先将训练集和测试集合并
# 数据预处理
# 合并数据集,方便同时对两个数据集进行清洗
full = pd.concat([train_data, test_data], axis=0, ignore_index=True)
full.shape
查看关系矩阵,初步找到与气温属性关系大的属性特征
# 关系矩阵
corr_df = train_data.corr()
print(corr_df['气温'].sort_values())
![在这里插入图片描述](https://img-blog.csdnimg.cn/753408c615344d6081a5022ed8ae6cd7.jpeg#pic_center)
full.info()
因为风速和风向与气温的关系系数较低且缺失值较多,先删除掉这两个特征属性
full.drop(['平均每小时风速', '主要每小时风向'], axis=1, inplace=True)
full.info()
属性(降水量、气温、湿球空气温度、露点空气温度、相对湿度、平均海平面压力、蒸气压)都有少量缺失值,采用均值填充
cols = ['降水量', '湿球空气温度', '露点空气温度', '相对湿度', '平均海平面压力', '蒸气压']
for col in cols:
full[col] = full[col].fillna(full[col].mean())
缺失值处理后的数据信息如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/4ef8e767f3044c62a2c9a2f5161be9f1.jpeg#pic_center)
特征工程
1.属性(降水量、湿球空气温度、露点空气温度、相对湿度、平均海平面压力、蒸气压)都是连续数值,需要规范化
from sklearn import preprocessing
numeric_cols = ['降水量', '湿球空气温度', '露点空气温度', '相对湿度', '平均海平面压力', '蒸气压']
scaler = preprocessing.StandardScaler()
full_standar = scaler.fit_transform(full[numeric_cols])
full_front = pd.DataFrame(full_standar, columns=numeric_cols)
full_front.head()
注意:这里我新建了一个full_front,后续还会有这类小的DataFrame,用来最后拼成总的处理好的数据 2.属性(地区、站号)绑定在一起,并且类似哑量处理,将数据全部表示为0,1
Location_Number = full[['地区', '站号']].copy()
Location_Number['地区0-站号0'] = [1 if i == 0 and j == 0 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区0-站号4'] = [1 if i == 0 and j == 4 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区0-站号21'] = [1 if i == 0 and j == 21 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区1-站号1'] = [1 if i == 1 and j == 1 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区2-站号2'] = [1 if i == 2 and j == 2 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区3-站号3'] = [1 if i == 3 and j == 3 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区4-站号5'] = [1 if i == 4 and j == 5 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区4-站号7'] = [1 if i == 4 and j == 7 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区4-站号9'] = [1 if i == 4 and j == 9 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区4-站号22'] = [1 if i == 4 and j == 22 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区5-站号6'] = [1 if i == 5 and j == 6 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区6-站号8'] = [1 if i == 6 and j == 8 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区7-站号110'] = [1 if i == 7 and j == 10 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区7-站号18'] = [1 if i == 7 and j == 18 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区7-站号20'] = [1 if i == 7 and j == 20 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区7-站号23'] = [1 if i == 7 and j == 23 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区8-站号11'] = [1 if i == 8 and j == 11 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区9-站号12'] = [1 if i == 9 and j == 12 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区10-站号13'] = [1 if i == 10 and j == 13 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区11-站号14'] = [1 if i == 11 and j == 14 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区11-站号17'] = [1 if i == 11 and j == 17 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区12-站号15'] = [1 if i == 12 and j == 15 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区13-站号16'] = [1 if i == 13 and j == 16 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
Location_Number['地区14-站号19'] = [1 if i == 14 and j == 19 else 0 for i, j in
zip(Location_Number['地区'], Location_Number['站号'])]
full_location = Location_Number.drop(['地区', '站号'], axis=1)
full_location
3.属性(年,月,日),对时间序列进行特征工程,尽可能如上操作一样,年份,月份,日都要哑量处理,将每天的时间进行分段编码
Date_df = full[['年', '月', '日']].copy()
Date_df['日期'] = Date_df['年'].map(str)+"-"+Date_df['月'].map(str)+"-"+Date_df['日'].map(lambda x: x.split(" ")[0])+ " "+Date_df['日'].map(lambda x: x.split(" ")[1])
Date_df['日期'] = pd.to_datetime(Date_df['日期'])
Date_df
![在这里插入图片描述](https://img-blog.csdnimg.cn/a0c29362bbc74014902f477077f39171.jpeg#pic_center)
year_df = pd.get_dummies(Date_df['年'])
month_df = pd.get_dummies(Date_df['月'])
day_df = pd.get_dummies(Date_df['日'].map(lambda x: x.split(" ")[0]))
hour_df = Date_df['日期'].dt.hour
# 将每天的时间分组
# 黎明:2:00-5:59、上午:6:00-10:59、中午:11:00-13:59、下午:14:00-17:59、晚上:18:00-21:59、午夜:22:00-1:59
def daypart(hour):
if hour in [2, 3, 4, 5]:
return "down"
elif hour in [6, 7, 8, 9, 10]:
return "morning"
elif hour in [11, 12, 13]:
return "noon"
elif hour in [14, 15, 16, 17]:
return "afternoon"
elif hour in [18, 19, 20, 21]:
return "evening"
else:
return "midnight"
hour_df = hour_df.apply(daypart)
hour_df = pd.get_dummies(hour_df)
full_datetime = pd.concat([year_df, month_df, day_df, hour_df], axis=1)
full_datetime
4.最后合并得到的所有数据
full_all = pd.concat([full_front, full_location, full_datetime], axis=1)
构建模型
建立训练数据集和测试数据集
from sklearn.model_selection import train_test_split
source_X = full_all.loc[0:1244735, :]
source_y = full.loc[0:1244735, '气温']
pred_X = full_all.loc[1244736:, :]
train_X, test_X, train_y, test_y = train_test_split(source_X, source_y, train_size=0.8, random_state=0)
print('原始数据集特征:', source_X.shape, '训练数据集特征:', train_X.shape, '测试数据集特征:', test_X.shape)
print('原始数据集标签:', source_y.shape, '训练数据集标签:', train_y.shape, '测试数据集标签:', test_y.shape)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ee4bc4630fae4fb1ad1150991b776e86.jpeg#pic_center)
模型构建
# 随机森林
import os
os.environ['CUDA_VISIBLE_DEVICES'] = "1"
from sklearn.ensemble import RandomForestRegressor
clf = RandomForestRegressor(random_state=0, n_estimators=200)
clf = clf.fit(train_X, train_y)
clf.score(test_X, test_y)
0.999366805329574
pred_y = clf.predict(pred_X)
location = test_data['站号']
date = test_data['日']
pred_df = pd.DataFrame({
'站号': location,
'日': date,
'气温': pred_y
})
# 保存结果
pred_df.to_csv('F:/DocumentFile/data/地区温度预测挑战赛公开数据/pred.csv', index=False)
这是第二次参加数据挖掘的比赛,大概排名在45/90,比起第一次还是有非常大的进步,但是由于这次的数据量较大,在模型的参数调优时,遇到一些小瓶颈,如果能得到较好的一些方法参数应该能将分数提高一些,或者在针对平均海平面压力和主要每小时风向时,用一些缺失值填补方法,而不是直接删除掉两个属性,也许也能让模型更加完善优化。还有在进行特征处理时,我处理的方法让模型的维度大大加大了,这也有不小的影响。在对不同类型数据进行特征处理时还是要多学习,期待下一次吧!Continue…
|