第十周周四

在搞数学建模竞赛,用python完成了数据分析。

复制代码
  1 import os
  2 import pandas as pd
  3 from sklearn.model_selection import train_test_split
  4 from sklearn.linear_model import LinearRegression
  5 from sklearn.metrics import mean_squared_error, r2_score
  6 import numpy as np
  7 import plotly.graph_objs as go
  8 from concurrent.futures import ProcessPoolExecutor
  9 from multiprocessing import freeze_support
 10 from statsmodels.tsa.statespace.sarimax import SARIMAX
 11 from datetime import datetime, timedelta
 12 
 13 # 定义函数读取单个文件的数据
 14 def read_file(file_path):
 15     return pd.read_csv(file_path, encoding='utf-8', delimiter=",")
 16 
 17 def main():
 18     # 定义第一个文件夹路径
 19     folder_path_1 = r"C:\Users\86155\Desktop\建模竞赛\2024校赛题目\2024校赛题目--C\附件2:2014年01月-2024年03月全国主要城市空气质量数据\all\all1"
 20 
 21     # 初始化一个空 DataFrame
 22     all_data_1 = pd.DataFrame()
 23 
 24     # 定义并行处理的进程数
 25     num_processes = os.cpu_count()  # 使用CPU核心数作为进程数
 26     i = 0
 27     # 使用进程池并行读取所有文件的数据
 28     with ProcessPoolExecutor(max_workers=num_processes) as executor:
 29         # 提交所有文件读取任务
 30         futures = [executor.submit(read_file, os.path.join(folder_path_1, file_name)) for file_name in
 31                    os.listdir(folder_path_1) if file_name.endswith(".csv")]
 32 
 33         # 获取所有任务的结果
 34         for future in futures:
 35             i += 1
 36             print(i)
 37             data = future.result()
 38             all_data_1 = pd.concat([all_data_1, data], ignore_index=True)
 39 
 40     # 对第一个文件数据进行清洗和预处理(这里假设无需清洗和预处理)
 41 
 42     # 将日期列和小时列合并为日期时间类型
 43     all_data_1['datetime'] = pd.to_datetime(
 44         all_data_1['date'].astype(str) + ' ' + all_data_1['hour'].astype(str).str.zfill(2), format='%Y%m%d %H')
 45     # 删除原始的日期和小时列
 46     all_data_1.drop(columns=['date', 'hour'], inplace=True)
 47 
 48     # 用副本解决 'SettingWithCopyWarning' 问题
 49     shijiazhuang_data = all_data_1[['datetime', '石家庄', 'type']].copy()
 50 
 51     # 将日期设置为索引
 52     shijiazhuang_data.set_index('datetime', inplace=True)
 53 
 54     # 提取AQI指数的数据
 55     aqi_data = shijiazhuang_data[shijiazhuang_data['type'] == 'AQI']
 56 
 57     # 定义第二个文件路径
 58     file_path_2 = r"C:\Users\86155\Desktop\建模竞赛\2024校赛题目\2024校赛题目--C\附件1:2014年01月-2024年02月石家庄天气数据.xlsx"
 59 
 60     # 读取第二个文件的数据
 61     weather_factors = pd.read_excel(file_path_2)
 62     if weather_factors.empty:
 63         print("文件未打开")
 64 
 65     # 将日期列和小时列合并为日期时间类型
 66     weather_factors['datetime'] = pd.to_datetime(weather_factors[''].astype(str) + '-' +
 67                                                  weather_factors[''].astype(str).str.zfill(2) + '-' +
 68                                                  weather_factors[''].astype(str).str.zfill(2) + ' ' +
 69                                                  weather_factors[''].astype(str).str.zfill(2) + ':00')
 70     # 将缺失数据(9999)替换为 NaN
 71     weather_factors.replace(9999, pd.NA, inplace=True)
 72 
 73     # 合并两个数据集
 74     merged_data = pd.merge(aqi_data, weather_factors, on='datetime')
 75 
 76     # 划分特征和目标变量
 77     X = merged_data[['气温(因子10)℃', '露点温度(因子10)℃', '海平面气压(因子10)Pa', '风向(由北顺时针)°',
 78                      '风速(因子10)m/s', '天空状况总覆盖代码', '液体沉积深度(因子10,周期6小时)mm']]
 79     y = merged_data['石家庄']
 80 
 81     # 确保在划分训练集和测试集之前用平均值填充NaN
 82     X.fillna(X.mean(), inplace=True)
 83     y.fillna(y.mean(), inplace=True)
 84 
 85     # 划分训练集和测试集
 86     X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
 87 
 88     # 建立线性回归模型
 89     model = LinearRegression()
 90 
 91     # 在划分和训练模型之前解决 'Input contains NaN, infinity or a value too large for dtype' 问题
 92     X_train.fillna(X_train.mean(), inplace=True)
 93     y_train.fillna(y_train.mean(), inplace=True)
 94     X_train = X_train.astype(float).fillna(5)
 95     y_train = y_train.astype(float).fillna(5)
 96     # 在处理过的训练集上训练模型
 97     model.fit(X_train, y_train)
 98 
 99     # 获取特征的系数
100     feature_coef = pd.Series(model.coef_, index=X.columns).abs().sort_values(ascending=False)
101 
102     # 打印出对 AQI 影响最大的因素
103     print("对 AQI 影响最大的因素:", feature_coef.index[0])
104 
105     X_test = X_test.astype(float).fillna(5)
106     # 在测试集上进行预测
107     y_pred = model.predict(X_test)
108 
109     # 计算均方误差
110     mse = mean_squared_error(y_test, y_pred)
111     print("均方误差:", mse)
112 
113     # 计算均方根误差(RMSE)
114     rmse = np.sqrt(mse)
115     print("均方根误差(RMSE):", rmse)
116 
117     # 计算决定系数(R^2)
118     r2 = r2_score(y_test, y_pred)
119     print("决定系数(R^2):", r2)
120 
121     # 创建交互式图表
122     fig = go.Figure()
123 
124     # 添加原始数据曲线
125     fig.add_trace(go.Scatter(x=merged_data['datetime'], y=merged_data['石家庄'], mode='lines', name='石家庄原始AQI数据'))
126 
127     # 处理预测特征集前的缺失值
128     weather_factors.fillna(method='ffill', inplace=True)  # 以前向填充方式处理缺失值
129 
130     # 确保特征匹配(假设这些是训练模型时使用的特征)
131     selected_features = ['气温(因子10)℃', '露点温度(因子10)℃', '海平面气压(因子10)Pa',
132                          '风向(由北顺时针)°', '风速(因子10)m/s', '天空状况总覆盖代码',
133                          '液体沉积深度(因子10,周期6小时)mm']
134     weather_factors_for_prediction = weather_factors[selected_features]
135 
136     # 再次确认无 NaN 或 NA
137     weather_factors_for_prediction.fillna(weather_factors_for_prediction.mean(), inplace=True)
138 
139     # 添加预测AQI指数曲线
140     # SARIMA模型预测
141     train = merged_data[['datetime', '石家庄']].copy()  # 使用历史AQI数据作为时间序列
142     train.set_index('datetime', inplace=True)
143     order = (1, 1, 1)  # ARIMA模型的阶数
144     seasonal_order = (1, 1, 1, 12)  # 季节性阶数
145     model_sarima = SARIMAX(train, order=order, seasonal_order=seasonal_order, enforce_stationarity=False, enforce_invertibility=False)
146     results_sarima = model_sarima.fit()
147 
148 
149     # 定义当前日期为2024年3月1日
150     current_date = pd.to_datetime('2024-03-01')
151 
152     # 计算未来两三个月后的日期
153     future_date = current_date + pd.DateOffset(months=3)  # 或者 pd.DateOffset(months=3) 如果是未来三个月
154 
155     # 将日期转换为字符串形式
156     end_date_str = future_date.strftime('%Y-%m-%d')
157 
158     # 将字符串日期转换为 pandas 的 datetime 格式
159     end_date = pd.to_datetime(end_date_str)
160 
161     print(len(train))
162 
163     forecast = results_sarima.predict(start='2024-03-01', end='2024-06-30', dynamic=False)  # 预测未来60天,每天24个小时
164     fig.add_trace(go.Scatter(x=forecast.index, y=forecast, mode='lines', name='石家庄预测AQI数据'))
165 
166     # 为每个特征创建曲线并添加到图表中
167     for feature in selected_features:
168         # 获取特征的预测值
169         feature_pred = model.predict(weather_factors_for_prediction)
170         fig.add_trace(go.Scatter(x=merged_data['datetime'], y=merged_data[feature], mode='lines', name=feature + '_原始值', xaxis='x1'))
171         fig.add_trace(go.Scatter(x=merged_data['datetime'], y=feature_pred, mode='lines', name=feature + '_预测值', xaxis='x1'))
172 
173     # 设置图表布局
174     fig.update_layout(
175         title='石家庄AQI指数预测',
176         xaxis_title='日期',
177         yaxis_title='AQI指数'
178     )
179 
180     # 显示图表
181     fig.show()
182 
183 
184 if __name__ == '__main__':
185     freeze_support()
186     main()
复制代码

 

posted @   a_true  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示