```markdown
是的,你完全可以使用 **Jupyter Notebook** 来完成这个项目的全部任务,而且对于新手来说,**Jupyter Notebook 比 PyCharm 更适合学习和调试**,原因如下:
- 支持 **分块运行代码**(Cell-by-cell execution),便于逐步调试;
- 内置图形显示,可视化结果直接嵌入页面;
- 支持 Markdown 注释,方便添加说明与教学笔记;
- 特别适合数据分析、机器学习和时间序列建模等任务。
---
### ✅ 如何在 Jupyter Notebook 中完成该项目?
我们将整个项目拆分为多个代码单元格(Cell),每一步清晰可见,最终可导出为 `.ipynb` 文件或 HTML/PDF 报告。
---
## 🚀 全流程演示:在 Jupyter Notebook 中运行代码并展示结果
> 下面是一个完整的 Jupyter Notebook 流程模拟,包含注释、代码、预期输出和图表描述。
---
### 🔹 Step 1: 启动环境 & 导入库
```python
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
# 设置中文字体(防止中文乱码)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")
%matplotlib inline
print("环境准备完毕!")
```
✅ 输出:
```
环境准备完毕!
```
---
### 🔹 Step 2: 加载数据
```python
# 设置文件路径
file_path = r"D:\air+quality\lanzhou.xlsx"
# 读取 Excel 数据
df = pd.read_excel(file_path, sheet_name='lanzhou', engine='openpyxl')
# 显示前5行
df.head()
```
✅ 输出表格示例(部分字段):
| 日期 | 质量等级 | AQI指数 | PM2.5 | PM10 | So2 | No2 | Co | O3 |
|------------|-----------|---------|--------|-------|------|------|-------|-----|
| 2013-10-29 | 良 | 86 | 61 | 115 | 27 | 29 | 1.39 | 18 |
| 2013-10-30 | 良 | 77 | 56 | 74 | 24 | 30 | 1.30 | 26 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
📌 提示:若提示找不到文件,请检查路径是否正确,建议使用右键复制路径粘贴。
---
### 🔹 Step 3: 数据清洗
```python
# 清理列名
df.columns = df.columns.str.strip()
# 转换日期列
df['日期'] = pd.to_datetime(df['日期'], errors='coerce')
df.dropna(subset=['日期'], inplace=True)
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)
# 数值列转换
numeric_cols = ['PM2.5', 'PM10', 'So2', 'No2', 'Co', 'O3', 'AQI指数']
df[numeric_cols] = df[numeric_cols].apply(pd.to_numeric, errors='coerce')
# 插值填补缺失值
df[numeric_cols] = df[numeric_cols].interpolate(method='linear')
# 重采样为每日平均
df_daily = df[numeric_cols].resample('D').mean()
# 查看形状和是否有缺失
print(f"数据维度: {df_daily.shape}")
print(f"缺失值总数: {df_daily.isnull().sum().sum()}")
df_daily.head()
```
✅ 输出:
```
数据维度: (xxx, 7)
缺失值总数: 0
```
✅ 表格预览正常,数据已对齐且无缺失。
---
### 🔹 Step 4: 时间序列可视化
```python
# 绘制 PM2.5 趋势图
plt.figure(figsize=(14, 6))
plt.plot(df_daily.index, df_daily['PM2.5'], label='PM2.5', color='tab:blue', linewidth=1.2)
plt.title('兰州 PM2.5 长期变化趋势(2013–2022)', fontsize=16)
plt.xlabel('日期')
plt.ylabel('PM2.5 浓度 (μg/m³)')
plt.legend()
plt.grid(True, alpha=0.4)
plt.tight_layout()
plt.show()
```
📊 图表效果描述:
- X轴:时间跨度从2013年到2022年;
- Y轴:PM2.5浓度;
- 可见明显的**季节性波动**:冬季高、夏季低;
- 存在几个极端峰值(如2013年底、2021年沙尘暴期间)。
---
### 🔹 Step 5: 季节性分解(STL)
```python
from statsmodels.tsa.seasonal import STL
# 仅取部分数据避免过长
subset = df_daily['PM2.5']['2014':'2020'].copy()
stl = STL(subset, seasonal=13)
result = stl.fit()
fig = result.plot()
fig.set_size_inches(12, 8)
plt.suptitle("PM2.5 季节性分解(趋势 + 季节性 + 残差)", fontsize=16)
plt.tight_layout()
plt.show()
```
📊 图表分为四部分:
1. **Observed**:原始观测值;
2. **Trend**:长期上升/下降趋势;
3. **Seasonal**:年度周期性(每年冬天升高);
4. **Residual**:无法解释的随机波动。
📌 结论:兰州空气质量具有显著**年周期性**。
---
### 🔹 Step 6: 自相关图(ACF/PACF)
```python
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
fig, ax = plt.subplots(2, 1, figsize=(10, 6), sharex=True)
plot_acf(df_daily['PM2.5'].dropna(), lags=40, ax=ax[0])
plot_pacf(df_daily['PM2.5'].dropna(), lags=40, ax=ax[1])
ax[0].set_title("自相关函数(ACF)")
ax[1].set_title("偏自相关函数(PACF)")
plt.xlabel("滞后阶数")
plt.tight_layout()
plt.show()
```
📊 观察要点:
- ACF 缓慢衰减 → 表明存在趋势,需差分;
- PACF 在 lag=2 后截尾 → 建议 AR(p=2);
- 最终可设 ARIMA(2,1,2)。
---
### 🔹 Step 7: 拆分训练测试集 & 训练 ARIMA
```python
from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import mean_absolute_error, mean_squared_error
import warnings
warnings.filterwarnings("ignore")
# 拆分(最后30天为测试)
train = df_daily['PM2.5'][:-30]
test = df_daily['PM2.5'][-30:]
# 训练模型
model = ARIMA(train, order=(2,1,2))
arima_result = model.fit()
# 预测
forecast = arima_result.forecast(steps=len(test))
# 评估
mae = mean_absolute_error(test, forecast)
rmse = np.sqrt(mean_squared_error(test, forecast))
print(f"🔹 MAE: {mae:.2f} μg/m³")
print(f"🔹 RMSE: {rmse:.2f} μg/m³")
# 绘图对比
plt.figure(figsize=(12, 5))
plt.plot(train.index, train, label="训练集", color="blue")
plt.plot(test.index, test, label="真实值", color="green", linewidth=2)
plt.plot(test.index, forecast, label="预测值", color="red", linestyle="--", linewidth=2)
plt.title("ARIMA 模型预测效果对比")
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(rotation=30)
plt.tight_layout()
plt.show()
```
✅ 输出示例:
```
🔹 MAE: 24.31 μg/m³
🔹 RMSE: 30.18 μg/m³
```
📊 图像显示:
- 红色虚线为预测曲线;
- 基本跟随绿色真实值波动;
- 在突变点(如突然恶化)误差较大。
---
### 🔹 Step 8: LSTM 模型(可选高级部分)
```python
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
# 标准化
scaler = MinMaxScaler()
scaled = scaler.fit_transform(df_daily[['PM2.5']].dropna())
# 构造监督学习数据
def create_sequences(data, seq_length):
X, y = [], []
for i in range(len(data) - seq_length):
X.append(data[i:i+seq_length])
y.append(data[i+seq_length])
return np.array(X), np.array(y)
SEQ_LENGTH = 7
X, y = create_sequences(scaled, SEQ_LENGTH)
X = X.reshape(X.shape[0], X.shape[1], 1)
# 划分
split = int(0.8 * len(X))
X_train, X_test = X[:split], X[split:]
y_train, y_test = y[:split], y[split:]
# 构建模型
lstm_model = Sequential([
LSTM(50, activation='relu', input_shape=(SEQ_LENGTH, 1)),
Dense(1)
])
lstm_model.compile(optimizer='adam', loss='mse')
# 训练(少量 epoch 快速验证)
history = lstm_model.fit(X_train, y_train, epochs=10, batch_size=32, verbose=1)
# 预测
lstm_pred = lstm_model.predict(X_test)
lstm_pred = scaler.inverse_transform(lstm_pred)
y_test_inv = scaler.inverse_transform(y_test)
# 评估
mae_lstm = mean_absolute_error(y_test_inv, lstm_pred)
rmse_lstm = np.sqrt(mean_squared_error(y_test_inv, lstm_pred))
print(f"🔹 LSTM MAE: {mae_lstm:.2f}")
print(f"🔹 LSTM RMSE: {rmse_lstm:.2f}")
```
✅ 输出示例:
```
Epoch 1/10 - loss: 0.0012
...
Epoch 10/10 - loss: 0.0003
🔹 LSTM MAE: 19.45
🔹 LSTM RMSE: 26.83
```
📌 说明:LSTM 效果略优于 ARIMA,尤其在捕捉非线性变化方面表现更好。
---
### 🔹 Step 9: 将成果打包成报告
你可以使用以下命令将 `.ipynb` 导出为专业文档:
```bash
# 导出为 HTML(可在浏览器打开分享)
jupyter nbconvert --to html "兰州空气质量分析.ipynb"
# 导出为 PDF(需安装 LaTeX)
jupyter nbconvert --to pdf "兰州空气质量分析.ipynb"
```
---
### ✅ 总结:为什么推荐 Jupyter Notebook?
| 优势 | 说明 |
|------|------|
| ✅ 分步执行 | 每个 Cell 单独运行,不怕崩溃重来 |
| ✅ 实时可视化 | 图表直接显示在下方,无需弹窗 |
| ✅ 文档一体化 | 代码 + 文字说明 + 图形 = 完整报告 |
| ✅ 适合教学 | 非常适合“手把手教学”场景 |
| ✅ 社区资源丰富 | Kaggle、Colab、GitHub 上大量案例 |
---
### ✅ 知识点(列出解答该问题需要的知识点)
1. **Jupyter Notebook 使用基础**:支持交互式编程,每个 cell 可独立运行,适合数据分析全流程开发与调试。
2. **数据可视化集成能力**:Matplotlib/Seaborn 图表能在 notebook 中原生渲染,无需额外 GUI 支持。
3. **Notebook 导出功能**:可通过 nbconvert 将分析过程导出为 HTML 或 PDF,便于汇报与存档。
```