查看原文
其他

数据分析实战—未来天气预测

王海华 模型视角 2023-08-17

如何预测未来的天气?这是很多人关心的话题,无论是农民期待雨水滋润庄稼,还是旅行者计划周末的户外活动,都离不开对天气的了解和预测。一场及时的雨,或许是农作物的生机;一个晴朗的周末,或许是家庭欢聚的完美时光。天气预测早已不仅仅是科学的探索,更是日常生活的一部分,是文化、经济、社交的交织。

然而,天气的变化千变万化,复杂到令人眼花缭乱。那么,我们究竟如何捕捉风的轻抚、雨的低语、云的流动?科学家们凭借气象站的观测、卫星的眼睛,以及最重要的,数据科学的力量,试图解读天气的密码,预知未来的风云。

借助18个欧洲城市的详尽气象记录,我将带您走近这一神奇的科学领域,一同探索如何用随机森林的智慧、算法的精确,去描绘明天的天空。未来的降雨,将不再是未知的迷雾,而是科学与自然的和谐乐章。

数据收集、选择和处理

最初的气象数据从ECA&D[1]检索,该项目提供了欧洲和地中海各气象站的每日观测数据。选择了18个欧洲城市或地方,其中多个每日观测数据在2000年至2010年之间可用。这些地方包括瑞士的巴塞尔、匈牙利的布达佩斯、德国的德累斯顿、杜塞尔多夫、卡塞尔、慕尼黑、荷兰的De Bilt和Maastricht、英国的希思罗、斯洛文尼亚的卢布尔雅那、瑞典的马尔默和斯德哥尔摩、法国的蒙特利马尔、佩皮尼昂和图尔、挪威的奥斯陆、意大利的罗马和奥地利的索恩布利克。

这18个地点的每日气象观测记录跨越不同的时间,其中一些回溯到19世纪。但是,在这里我们仅选择了从2000年到2010年的时间跨度共有3654个每日观测数据。然后从这18个地点的所有数据中构建数据集。

此外,数据还包括不同的观测值。虽然所有选定的地点都提供了“平均温度”、“最高温度”和“最低温度”的数据,我们还包括了变量“云覆盖率”、“风速”、“阵风”、“湿度”、“压力”、“全球辐射”、“降水量”、“阳光时间”等的数据。

在收集数据后,对数据进行了非常基本的清理。删除了>5% 无效条目(“-9999”)的列,保留了<=5% 无效条目的列,但将无效条目替换为平均值。这导致了165个变量(或特征)在3654天的过程中。最后,我们转换了几个数据单位,以使现有值的范围更为相似。这使数据更适合用于机器学习或深度学习,甚至不需要额外的处理。我们故意不选择完全标准化数据,因为我们想保持所呈现的单位和值尽可能直观地可访问。现在,温度以摄氏度表示,风速和阵风以米/秒表示,湿度以百分比的分数表示,海平面压力以1000 hPa表示,全球辐射以100 W/m^2表示,降水量以厘米表示,阳光以小时表示。

变量的物理单位:

原始数据单位:

  • CC : 云覆盖八分之几
  • DD : 风向,以度为单位
  • FG : 风速,以0.1米/秒为单位
  • FX : 阵风,以0.1米/秒为单位
  • HU : 湿度,以1%为单位
  • PP : 海平面压力,以0.1 hPa为单位
  • QQ : 全球辐射,以W/m^2为单位
  • RR : 降水量,以0.1毫米为单位
  • SS : 阳光时间,以0.1小时为单位
  • TG : 平均温度,以0.1°C为单位
  • TN : 最低温度,以0.1°C为单位
  • TX : 最高温度,以0.1°C为单位

转换后:

  • CC : 云覆盖八分之几
  • DD : 风向,以度为单位
  • FG : 风速,以1米/秒为单位
  • FX : 阵风,以1米/秒为单位
  • HU : 湿度,以100%的分数表示
  • PP : 海平面压力,以1000 hPa为单位
  • QQ : 全球辐射,以100 W/m^2为单位
  • RR : 降水量,以10毫米为单位
  • SS : 阳光时间,以1小时为单位
  • TG : 平均温度,以1°C为单位
  • TN : 最低温度,以1°C为单位
  • TX : 最高温度,以1°C为单位
# 导入所需的库
import pandas as pd

# 加载数据集
file_path = "data/weather_prediction_dataset.csv"
weather_data = pd.read_csv(file_path)

# 显示数据集的前五行
weather_data.head()

这是数据前5行的样本:

        DATE  MONTH  BASEL_cloud_cover  BASEL_humidity  BASEL_pressure  \
0 2000-01-01      1                  8            0.89          1.0286   
1 2000-01-02      1                  8            0.87          1.0318   
2 2000-01-03      1                  5            0.81          1.0314   
3 2000-01-04      1                  7            0.79          1.0262   
4 2000-01-05      1                  5            0.90          1.0246   

   BASEL_global_radiation  BASEL_precipitation  BASEL_sunshine  \
0                    0.20                 0.03             0.0   
1                    0.25                 0.00             0.0   
2                    0.50                 0.00             3.7   
3                    0.63                 0.35             6.9   
4                    0.51                 0.07             3.7   

   BASEL_temp_mean  BASEL_temp_min  ...  BASEL_humidity_lag_3  \
0              2.9             1.6  ...                   NaN   
1              3.6             2.7  ...                   NaN   
2              2.2             0.1  ...                   NaN   
3              3.9             0.5  ...                  0.89   
4              6.0             3.8  ...                  0.87   

   BASEL_pressure_lag_1  BASEL_pressure_lag_2  BASEL_pressure_lag_3  \
0                   NaN                   NaN                   NaN   
1                1.0286                   NaN                   NaN   
2                1.0318                1.0286                   NaN   
3                1.0314                1.0318                1.0286   
4                1.0262                1.0314                1.0318   

   BASEL_cloud_cover_lag_1  BASEL_cloud_cover_lag_2  BASEL_cloud_cover_lag_3  \
0                      NaN                      NaN                      NaN   
1                      8.0                      NaN                      NaN   
2                      8.0                      8.0                      NaN   
3                      5.0                      8.0                      8.0   
4                      7.0                      5.0                      8.0   

   BASEL_precipitation_lag_1  BASEL_precipitation_lag_2  \
0                        NaN                        NaN   
1                       0.03                        NaN   
2                       0.00                       0.03   
3                       0.00                       0.00   
4                       0.35                       0.00   

   BASEL_precipitation_lag_3  
0                        NaN  
1                        NaN  
2                        NaN  
3                       0.03  
4                       0.00  

[5 rows x 180 columns]

接下来将按照以下四个部分进行分析:

  • 数据完整性分析:检查数据中的缺失值和异常值。
  • 季节性和趋势分析:分析温度、降水量等的季节性变化。
  • 城市间比较:比较不同城市的气象特性。
  • 建立预测模型:数据处理+机器学习模型预测未来一天的气温、湿度等。

数据完整性分析

首先,我们将检查数据集中的缺失值和异常值

# 检查数据集中的缺失值
missing_data_summary = weather_data.isnull().sum()

# 显示具有缺失值的列(如果有的话)
missing_columns = missing_data_summary[missing_data_summary > 0]
missing_columns
Series([], dtype: int64)

在数据集中没有发现缺失值。现在,我们将进一步检查数据中的异常值。由于数据集较大,我们将选择一些代表性的变量进行检查。

季节性和趋势分析

我们将分析巴塞尔(瑞士)的温度和降水量的季节性和趋势变化。选择巴塞尔作为示例城市,但我们可以根据需要分析其他城市。让我们首先可视化这些变量的时间序列

import matplotlib.pyplot as plt

# 将日期列转换为日期时间格式
weather_data['DATE'] = pd.to_datetime(weather_data['DATE'], format='%Y%m%d')

# 选择巴塞尔的温度和降水量数据
basel_temp_mean = weather_data[['DATE''BASEL_temp_mean']]
basel_precipitation = weather_data[['DATE''BASEL_precipitation']]

# 绘制温度时间序列
plt.figure(figsize=(126))
plt.plot(basel_temp_mean['DATE'], basel_temp_mean['BASEL_temp_mean'], label='Mean Temperature (°C)')
plt.xlabel('Date')
plt.ylabel('Temperature (°C)')
plt.title('Mean Temperature Trend in Basel (Switzerland)')
plt.legend()
plt.show()

# 绘制降水量时间序列
plt.figure(figsize=(126))
plt.plot(basel_precipitation['DATE'], basel_precipitation['BASEL_precipitation'], label='Precipitation (cm)')
plt.xlabel('Date')
plt.ylabel('Precipitation (cm)')
plt.title('Precipitation Trend in Basel (Switzerland)')
plt.legend()
plt.show()

上述图表显示了巴塞尔(瑞士)的平均温度和降水量的时间序列。

  • 平均温度趋势:可以观察到明显的季节性变化,温度在夏季上升,在冬季下降。长期趋势似乎相对稳定,没有明显的上升或下降。
  • 降水量趋势:降水量也显示出一定的季节性变化,但不如温度明显。降水量的长期趋势也相对稳定。

城市间比较

接下来,我们将比较不同城市的气象特性。作为示例,我们可以比较2000年至2010年期间所有城市的平均温度和湿度

首先,我们将计算每个城市的平均温度和湿度。

# 从列名中提取城市名称
cities = list(set([col.split('_')[0for col in weather_data.columns if '_' in col]))

# 计算每个城市的平均温度和湿度
city_avg_temp_humidity = []
for city in cities:
    temp_cols = [col for col in weather_data.columns if city in col and 'temp_mean' in col]
    humidity_cols = [col for col in weather_data.columns if city in col and 'humidity' in col]
    avg_temp = weather_data[temp_cols].mean().mean()
    avg_humidity = weather_data[humidity_cols].mean().mean()
    city_avg_temp_humidity.append((city, avg_temp, avg_humidity))

# 转换为 DataFrame
city_avg_temp_humidity_df = pd.DataFrame(city_avg_temp_humidity, columns=['City''Avg_Temperature (°C)''Avg_Humidity'])
city_avg_temp_humidity_df = city_avg_temp_humidity_df.sort_values(by='Avg_Temperature (°C)', ascending=False)

# 显示结果
city_avg_temp_humidity_df

下表展示了2000年至2010年期间18个欧洲城市的平均温度和湿度:

  • 温度比较:罗马和佩皮尼昂是平均温度最高的城市,而索恩布利克的平均温度最低。
  • 湿度比较:索恩布利克的平均湿度最高,而佩皮尼昂的平均湿度最低。

机器学习模型

我们将使用巴塞尔(Basel)的数据来预测未来一天的降雨。以下是我们的分析流程:

  1. 选择目标变量和特征我们将选择降雨作为目标变量,并选择与降雨可能相关的其他气象变量作为特征。特征可能包括温度、湿度、压力等。

  2. 创建滞后特征由于我们是基于过去的观测来预测未来的降雨,所以我们将创建滞后特征。这些特征表示过去的观测值。

  3. 数据分割我们将数据分割为训练集、验证集和测试集。

  4. 模型选择和训练我们将选择一个适合时间序列预测的模型,并使用训练集进行训练。

  5. 预测和评估我们将使用模型对未来一天的降雨进行预测,并使用测试集评估模型的性能。

首先,我们将从巴塞尔的数据中选择目标变量和特征,并创建滞后特征。

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 选择巴塞尔的降雨数据作为目标变量
target_variable = 'BASEL_precipitation'
features = ['BASEL_temp_mean''BASEL_humidity''BASEL_pressure''BASEL_cloud_cover']

# 创建滞后特征
lag_days = 3
for feature in features + [target_variable]:
    for lag in range(1, lag_days + 1):
        weather_data[f'{feature}_lag_{lag}'] = weather_data[feature].shift(lag)

# 选择特征和目标变量
selected_features = [f'{feature}_lag_{lag}' for feature in features for lag in range(1, lag_days + 1)]
selected_features += features
X = weather_data[selected_features][lag_days:]
y = weather_data[target_variable][lag_days:]

# 标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, shuffle=False)

# 显示选定的特征和目标变量的前几行
X_train[:5], y_train[:5]

我们已经选择了与降雨相关的特征,并创建了过去3天的滞后特征。特征包括巴塞尔的平均温度、湿度、压力和云覆盖率。接下来,我们将选择一个合适的预测模型并进行训练。

由于我们正在处理一个回归问题(预测连续的降雨量),我们可以考虑使用诸如线性回归、随机森林回归或梯度增强回归等回归模型。这里我们使用随机森林回归模型来预测巴塞尔(Basel)未来一天的降雨量

首先,我们将训练随机森林回归模型,并在训练集上评估其性能。然后,我们将使用模型在测试集上进行预测,并评估其性能。

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error
import numpy as np

# 创建随机森林回归模型
rf_regressor = RandomForestRegressor(n_estimators=100, random_state=42)

# 训练模型
rf_regressor.fit(X_train, y_train)

# 在训练集上进行预测
y_train_pred = rf_regressor.predict(X_train)

# 计算训练集的性能指标
train_mae = mean_absolute_error(y_train, y_train_pred)
train_rmse = np.sqrt(mean_squared_error(y_train, y_train_pred))

# 在测试集上进行预测
y_test_pred = rf_regressor.predict(X_test)

# 计算测试集的性能指标
test_mae = mean_absolute_error(y_test, y_test_pred)
test_rmse = np.sqrt(mean_squared_error(y_test, y_test_pred))

train_mae, train_rmse, test_mae, test_rmse

随机森林回归模型的训练和测试性能如下:

训练集:

  • 平均绝对误差 (MAE):0.0865 cm
  • 均方根误差 (RMSE):0.1651 cm 测试集:
  • 平均绝对误差 (MAE):0.2450 cm
  • 均方根误差 (RMSE):0.4743 cm

这些指标量化了模型预测与实际观测之间的误差。训练集上的误差较小,而测试集上的误差较大,这可能表明模型在训练数据上过拟合。我们可以通过调整模型参数、选择不同的特征或使用正则化技术来进一步改进模型

接下来,我们可以可视化测试集上的预测结果与实际降雨量的比较。这将帮助我们直观地了解模型的性能。

# 可视化测试集上的预测结果与实际降雨量的比较
plt.figure(figsize=(126))
plt.plot(weather_data['DATE'][lag_days:].iloc[-len(y_test):], y_test, label='Actual Precipitation (cm)')
plt.plot(weather_data['DATE'][lag_days:].iloc[-len(y_test):], y_test_pred, label='Predicted Precipitation (cm)', linestyle='--')
plt.xlabel('Date')
plt.ylabel('Precipitation (cm)')
plt.title('Predicted vs Actual Precipitation in Basel (Switzerland)')
plt.legend()
plt.show()

上图展示了巴塞尔(Basel)的实际降雨量与随机森林回归模型预测的降雨量之间的比较。实线表示实际降雨量,虚线表示预测的降雨量。

从图中可以看出,虽然模型捕捉到了一些降雨的趋势和模式,但在某些情况下也存在一些偏差。

总结

  • 我们选择了巴塞尔的降雨量作为预测目标,并使用了与降雨量可能相关的气象变量作为特征。
  • 我们使用随机森林回归模型进行了预测,并在测试集上评估了其性能。
  • 模型的预测与实际降雨量之间存在一些差异,可能需要进一步的特征工程和模型调优。

参考文献: 

[1] Klein Tank, A.M.G. and Coauthors, 2002. Daily dataset of 20th-century surface air temperature and precipitation series for the European Climate Assessment. Int. J. of Climatol., 22, 1441-1453.
[2] https://www.kaggle.com/datasets/thedevastator/weather-prediction


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存