城市尾气排放数据可视化分析系统 — 技术文档
1. 项目概述
1.1 项目简介
本系统是一个基于 Python Django 框架的城市尾气排放数据可视化分析平台,面向全国 36 个主要城市的机动车尾气排放数据,提供多维度的数据展示、智能分析和趋势预测能力。系统采用 B/S 架构,前端通过 ECharts 实现丰富的交互式图表,后端通过 Django + Pandas + NumPy 进行数据处理与统计分析,数据持久层使用 MySQL。
1.2 核心功能
| |
|---|
| KPI 卡片、智能分析结论、风险预警城市排名、低碳效率标杆、工作日排放对比、区域排放结构对比 |
| 3D 中国地图(省份下钻至城市)、桑基流图、漏斗图、极坐标柱状图、矩形树图 |
| 月度/年度趋势折线图、AQI 南丁格尔玫瑰图、月-周热力矩阵、污染物相关性矩阵、区域 CO2 箱线图、污染物堆叠面积图 |
| 能源类型饼图、绿色治理度仪表盘、多维雷达图、GDP-CO2 散点图、新能源占比排行 |
| 基于线性回归的 CO2 排放预测、Top 城市排放排行、年度 CO2/AQI 对比柱状图 |
| 分页查询、多条件筛选、CRUD 操作、CSV 导出 |
| 注册/登录/登出、个人资料编辑、密码修改、管理员用户管理(启用/禁用/删除) |
1.3 数据规模
- 覆盖城市:36 个(北京、上海、广州、深圳、天津、重庆、成都、杭州等)
- 数据字段:22 个维度(时间、地理、车辆、排放、气象、经济)





















2. 技术栈
2.1 后端
2.2 前端
| | |
|---|
| | |
| | |
| | 图表渲染引擎(折线、柱状、饼图、散点、热力图、桑基、漏斗、雷达、仪表盘、箱线图、地图) |
| | |
| | |
2.3 数据库
| |
|---|
| 8.0+,字符集 utf8mb4,排序规则 utf8mb4_unicode_ci |
| |
| |
3. 系统架构
3.1 整体架构
┌──────────────────────────────────────────────────────────┐│ 浏览器 (Client) ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────────┐ ││ │ Bootstrap│ │ ECharts │ │ ECharts │ │ dashboard │ ││ │ CSS/JS │ │ Core │ │ -GL │ │ .js │ ││ └─────────┘ └─────────┘ └─────────┘ └────────────┘ │└──────────────────────┬───────────────────────────────────┘ │ HTTP (JSON API / HTML)┌──────────────────────▼───────────────────────────────────┐│ Django 应用层 ││ ┌─────────────┐ ┌─────────────┐ ┌──────────────────┐ ││ │ urls.py │→ │ views.py │→ │ templates/ │ ││ │ (路由分发) │ │ (视图逻辑) │ │ (模板渲染) │ ││ └─────────────┘ └──────┬──────┘ └──────────────────┘ ││ │ ││ ┌─────────────┐ ┌──────▼──────┐ ┌──────────────────┐ ││ │ forms.py │ │ models.py │ │ admin.py │ ││ │ (表单验证) │ │ (数据模型) │ │ (后台管理) │ ││ └─────────────┘ └──────┬──────┘ └──────────────────┘ │└──────────────────────────┼───────────────────────────────┘ │ Django ORM┌──────────────────────────▼───────────────────────────────┐│ MySQL 数据库 ││ design_129_emission.emission_records │└──────────────────────────────────────────────────────────┘
3.2 数据流
CSV 文件 ──(import_emissions 命令)──→ MySQL ──(ORM Query)──→ Django View │ ┌─────────────┼─────────────┐ ▼ ▼ ▼ pandas DataFrame JSON API Template (聚合/统计/分析) (前端渲染) (HTML页面) │ │ └──────┬──────┘ ▼ ECharts 图表
3.3 项目目录结构
city/├── manage.py # Django 管理入口├── requirements.txt # Python 依赖├── city_emission_data.csv # 原始数据集 (4.16 MB)├── database_init.sql # 数据库初始化脚本├── design_129_emission.sql # 完整数据库导出│├── emission_system/ # Django 项目配置│ ├── __init__.py│ ├── settings.py # 全局配置(数据库、中间件、模板、静态文件)│ ├── urls.py # 根路由│ └── wsgi.py # WSGI 入口│├── dashboard/ # 核心应用│ ├── __init__.py│ ├── apps.py # 应用配置│ ├── models.py # 数据模型 (EmissionRecord)│ ├── views.py # 视图函数 (1731 行,含 15 个 API)│ ├── urls.py # 应用路由 (34 条)│ ├── forms.py # 表单类 (5 个)│ ├── admin.py # Admin 后台配置│ ├── management/│ │ └── commands/│ │ ├── import_emissions.py # CSV 数据导入命令│ │ └── seed_admin.py # 管理员账号初始化│ └── migrations/│ └── 0001_initial.py # 初始迁移│├── static/dashboard/│ ├── css/dashboard.css # 自定义样式 (2339 行)│ ├── js/dashboard.js # 前端逻辑 (1239 行)│ ├── img/ # 城市 SVG 插图│ └── vendor/ # 第三方库│ ├── bootstrap/ # Bootstrap 5 CSS/JS│ ├── bootstrap-icons/ # 图标字体│ ├── echarts/ # ECharts 核心 + china.js│ └── echarts-gl/ # ECharts 3D 扩展│├── templates/│ ├── base.html # 认证页面基础模板│ └── dashboard/│ ├── layout.html # 仪表盘布局(侧边栏 + 顶栏 + 内容区)│ ├── login.html # 登录页│ ├── register.html # 注册页│ ├── overview.html # 态势总览│ ├── geo.html # 地域分布│ ├── emission.html # 排放趋势│ ├── vehicle.html # 车辆结构│ ├── forecast.html # 预测分析│ ├── data_management.html # 数据管理│ ├── user_management.html # 用户管理│ ├── profile.html # 个人资料│ ├── password_change.html # 修改密码│ ├── record_form.html # 记录新增/编辑│ ├── record_confirm_delete.html # 记录删除确认│ └── partials/│ └── filter_dock.html # 筛选器组件│└── docs/ ├── city_drilldown_technical_doc.md └── technical_document.md # 本文档
4. 数据模型
4.1 EmissionRecord 模型
系统核心数据模型,存储每条城市尾气排放记录。
class EmissionRecord(models.Model): # ── 地理维度 ── city = CharField(max_length=50) # 城市名称 province = CharField(max_length=50) # 省份名称 region = CharField(max_length=30) # 区域(华东、华南等) # ── 时间维度 ── date = DateField() # 具体日期 year = PositiveSmallIntegerField() # 年份(冗余字段,加速查询) month = PositiveSmallIntegerField() # 月份(冗余字段) weekday = PositiveSmallIntegerField() # 星期几(1=周一,7=周日) is_workday = BooleanField() # 是否工作日 # ── 车辆维度 ── vehicle_stock_10k = FloatField() # 机动车保有量(万辆) new_energy_ratio = FloatField() # 新能源车占比(0-1) gasoline_ratio = FloatField() # 汽油车占比(0-1) diesel_ratio = FloatField() # 柴油车占比(0-1) avg_vehicle_age = FloatField() # 平均车龄(年) # ── 排放维度 ── co2_emission = FloatField() # CO2 排放量(吨/日) co_emission = FloatField() # CO 排放量(吨/日) nox_emission = FloatField() # NOx 排放量(吨/日) pm25_contribution = FloatField() # PM2.5 贡献(微克/立方米) aqi_index = PositiveSmallIntegerField() # AQI 指数 # ── 气象维度 ── avg_temperature = FloatField() # 月均气温(摄氏度) humidity = FloatField() # 相对湿度(%) wind_speed = FloatField() # 平均风速(米/秒) # ── 经济维度 ── population_10k = PositiveIntegerField() # 人口(万人) gdp_100m = PositiveIntegerField() # GDP(亿元) # ── 系统字段 ── created_at = DateTimeField(auto_now_add=True) # 创建时间
4.2 数据库索引
| | |
|---|
| | |
| city, province, region, date, year, month | |
| | |
| | |
| | |
4.3 数据库初始化
CREATE DATABASE IF NOT EXISTS design_129_emission DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
5. API 接口文档
所有 API 均需登录认证(@login_required),返回 JSON 格式,支持筛选参数。
5.1 公共筛选参数
5.2 API 列表
5.2.1 GET /api/options/
功能:获取筛选器选项数据
返回:
{ "ok": true, "data": { "provinces": ["上海市", "云南省", ...], "cities_by_province": { "上海市": ["上海"], "云南省": ["昆明"], ... }, "years": [2019, 2020, 2021, 2022, 2023] }}
5.2.2 GET /api/summary/
功能:态势总览 KPI 数据与区域排放对比
返回:
{ "ok": true, "empty": false, "data": { "cards": [ { "key": "co2", "label": "CO2日排放总量", "value": 123.45, "unit": "万吨", "trend": -2.3 } ], "meta": { "records": 5000, "cities": 36, "provinces": 30, "regions": 7, "year_range": [2019, 2023] }, "region_mix": [ { "region": "华东", "co2": 50000.00, "aqi": 85.3, "nox": 3000.00, "city_count": 8 } ] }}
5.2.3 GET /api/trends/
功能:时间趋势数据(月度、年度、星期维度)
返回:
{ "data": { "monthly": [ { "label": "2023-01", "co2": 50000, "co": 3000, "nox": 2000, "pm25": 45.2, "aqi": 85.3, "new_energy": 15.2 } ], "yearly": [ { "year": 2023, "co2": 600000, "nox": 24000, "aqi": 82.1, "vehicle": 350.5, "new_energy": 18.3 } ], "weekday": [ { "weekday": 1, "is_workday": true, "co2": 450.5, "aqi": 85.3 } ] }}
5.2.4 GET /api/geo/
功能:地理分布数据(省份和城市级 CO2 排放、AQI 等)
返回:
{ "data": { "provinces": [ { "name": "广东省", "geo_name": "广东", "region": "华南", "co2": 80000.00, "aqi": 78.5, "coord": [113.2669, 23.1333] } ], "cities": [ { "name": "广州", "province": "广东省", "co2": 25000.00, "aqi": 75.2, "coord": [113.2644, 23.1291] } ] }}
5.2.5 GET /api/geo-province/?province=广东省
功能:省份下钻,获取指定省份内城市级数据
参数:province(必填)
返回:与 /api/geo/ 结构类似,但仅包含指定省份的城市数据,另含 funnel、treemap、sankey 图表数据。
5.2.6 GET /api/charts/
功能:综合图表数据(车辆混合、污染物混合、AQI 南丁格尔、省份漏斗、桑基、雷达、仪表盘、散点、热力图、相关性矩阵、矩形树图、箱线图、Top 城市)
5.2.7 GET /api/geo-charts/
功能:地域分布页专用图表数据(漏斗、桑基、极坐标、矩形树图)
5.2.8 GET /api/emission-charts/
功能:排放趋势页专用图表数据(AQI 南丁格尔、热力矩阵、相关性矩阵、箱线图)
5.2.9 GET /api/vehicle-charts/
功能:车辆结构页专用图表数据(能源饼图、仪表盘、雷达、散点)
5.2.10 GET /api/forecast-detail/
功能:预测页 Top 城市排行数据
5.2.11 GET /api/insights/
功能:智能分析结论
返回:
{ "data": { "narrative": [ "华东区域累计 CO2 排放最高,占当前筛选范围的 32.5%。", "广东省广州是排放压力最高城市,CO2 累计 12.50 万吨。" ], "risk_rank": [ { "city": "广州", "province": "广东省", "score": 85.3, "co2": 25000, "aqi": 75.2, "new_energy": 18.5 } ], "efficiency_rank": [...], "pressure_rank": [...], "region_profile": [...], "workday_compare": [...] }}
5.2.12 GET /api/prediction/?horizon=6
功能:CO2 排放趋势预测(线性回归)
参数:horizon(预测月数,3-12,默认 6)
返回:
{ "data": { "history": [{ "label": "2023-01", "value": 50000 }], "forecast": [{ "label": "2024-01", "value": 52000 }], "method": "LinearRegression + monthly aggregate", "generated_at": "2024-01-15 10:30:00" }}
5.2.13 GET /api/export/
功能:CSV 数据导出(带 BOM 头,支持 Excel 直接打开)
返回:text/csv 文件下载
6. 核心业务逻辑
6.1 数据导入流程
# 1. 创建数据库mysql -u root -p < database_init.sql# 2. 执行迁移python manage.py migrate# 3. 导入 CSV 数据python manage.py import_emissions --path city_emission_data.csv --truncate# 4. 创建管理员python manage.py seed_admin --username admin --password 123456
import_emissions 命令流程:
- 事务内批量插入(
bulk_create,默认 batch_size=1000)
6.2 数据分析流程
视图函数中的数据分析遵循统一模式:
请求 → _filtered_queryset() → _frame() → pandas 聚合 → JSON 序列化 → 响应
- 筛选:
_filtered_queryset(request) 根据 GET 参数构建 Django QuerySet - 加载:
_frame(request, fields) 将 QuerySet 转为 pandas DataFrame - 分析:使用 pandas groupby/agg/corr 等进行多维聚合
- 序列化:
_num() / _int() 辅助函数处理 NaN/Inf 安全转换 - 返回:
_json() 封装 JsonResponse(ensure_ascii=False)
6.3 智能分析算法
6.3.1 风险评分模型
risk_score = ( minmax(co2) * 34 # CO2 权重 34% + minmax(nox) * 22 # NOx 权重 22% + minmax(aqi) * 24 # AQI 权重 24% + minmax(pm25) * 14 # PM2.5 权重 14% + (1 - minmax(new_energy)) * 6 # 新能源占比反向权重 6%)
其中 minmax() 为 Min-Max 归一化函数,将各指标映射到 [0, 1] 区间。
6.3.2 绿色治理度评分
green_score = clamp( 100 - avg_aqi / 3 - avg_co2 / max_co2 * 35 + avg_new_energy * 20, 0, 100)
6.3.3 CO2 预测模型
使用 scikit-learn 的 LinearRegression,以月度聚合的 CO2 总量为因变量,时间序列为自变量进行线性回归预测。若 scikit-learn 不可用,回退到 NumPy 的 polyfit 一次多项式拟合。
6.4 地图下钻机制
全国地图 (3D map3D) │ │ 点击省份 ▼省份下钻 (2D effectScatter) │ │ 点击面包屑"全国" ▼返回全国地图
- 前端维护
drilldown 状态对象(active, province, nationalData) - 点击省份时调用
/api/geo-province/ 获取城市级数据 - 地图从 3D map3D 切换为 2D effectScatter(涟漪散点)
7. 前端架构
7.1 页面结构
所有仪表盘页面继承 dashboard/layout.html,包含:
- 侧边栏 (
dimension-rail):品牌标识 + 分析维度导航 + 数据量统计 - 顶栏 (
workspace-topbar):页面标题 + 紧凑模式/回到顶部/个人中心/退出 - 内容区 (
dashboard-shell):各页面具体内容 - Toast 容器
7.2 JavaScript 模块结构
dashboard.js 采用 IIFE 封装,主要模块:
┌─ 状态管理 ──────────────────────────┐│ charts{} ECharts 实例缓存 ││ state{} 全局状态(选项、模态) ││ drilldown{} 下钻状态 │└────────────────────────────────────┘┌─ 工具函数 ──────────────────────────┐│ queryString() 构建筛选参数 ││ getJson() API 请求封装 ││ _num()/_int() 数值安全转换 ││ escapeHtml() XSS 防护 ││ showToast() 通知系统 │└────────────────────────────────────┘┌─ 图表渲染 ──────────────────────────┐│ renderMap() 3D/2D 地图 ││ renderTrend() 趋势折线图 ││ renderNightingale() 南丁格尔玫瑰图 ││ renderHeatmap() 热力矩阵 ││ renderCorrelation() 相关性矩阵 ││ renderSankey() 桑基流图 ││ renderFunnel() 漏斗图 ││ renderRadar() 雷达图 ││ renderGauge() 仪表盘 ││ renderScatter() 散点图 ││ renderBoxplot() 箱线图 ││ renderTreemap() 矩形树图 ││ renderPrediction() 预测折线图 ││ ... │└────────────────────────────────────┘┌─ 页面加载器 ────────────────────────┐│ loadOverviewPage() 态势总览 ││ loadGeoPage() 地域分布 ││ loadEmissionPage() 排放趋势 ││ loadVehiclePage() 车辆结构 ││ loadForecastPage() 预测分析 │└────────────────────────────────────┘┌─ 交互功能 ──────────────────────────┐│ initChartTools() 图表工具栏 ││ focusChart() 图表聚焦模态 ││ downloadChart() 图表导出PNG ││ enterDrilldown() 省份下钻 ││ exitDrilldown() 返回全国 ││ applyCompactMode() 紧凑模式 │└────────────────────────────────────┘
7.3 图表类型汇总
8. 用户认证与权限
8.1 认证机制
- 基于 Django 内置认证框架(
django.contrib.auth) - Session 认证,Cookie 存储 Session ID
- 所有仪表盘页面和 API 均需
@login_required 装饰器
8.2 权限模型
| |
|---|
| |
| 普通用户权限 + 用户管理 + Django Admin 后台 |
| |
8.3 表单类
| | |
|---|
| BootstrapAuthenticationForm | | |
| BootstrapUserCreationForm | | username, email, password1, password2 |
| BootstrapPasswordChangeForm | | old_password, new_password1, new_password2 |
| | username(只读), email, first_name, last_name |
| | 除 year/month/weekday/created_at 外全部字段 |
9. 部署与运维
9.1 环境要求
9.2 安装步骤
# 1. 克隆项目cd city/# 2. 安装依赖pip install -r requirements.txt# 3. 创建数据库mysql -u root -p < database_init.sql# 4. 配置数据库连接(环境变量或修改 settings.py)export MYSQL_DATABASE=design_129_emissionexport MYSQL_USER=rootexport MYSQL_PASSWORD=your_passwordexport MYSQL_HOST=localhostexport MYSQL_PORT=3306# 5. 执行数据库迁移python manage.py migrate# 6. 导入数据python manage.py import_emissions --path city_emission_data.csv --truncate# 7. 创建管理员python manage.py seed_admin --username admin --password your_password# 8. 启动服务python manage.py runserver 0.0.0.0:8000
9.3 环境变量
| | |
|---|
| design-129-emission-local-development-key | |
| | |
| | |
| | |
| | |
| | |
| | |
9.4 生产环境建议
安全配置:
性能优化:
- 开启 Django 缓存框架(Redis/Memcached)
数据备份:
10. 代码质量与规范
10.1 后端规范
- 视图函数使用
@login_required 和 @require_GET 装饰器进行访问控制 - 数据处理使用 pandas DataFrame,避免在 Python 层面手动循环
- 数值输出统一通过
_num() / _int() 处理 NaN/Inf 安全转换 - JSON 响应使用
ensure_ascii=False 支持中文直接输出 - 数据库操作使用
@transaction.atomic 保证事务一致性
10.2 前端规范
- 图表渲染使用
safeRender() 包装,捕获异常并显示错误状态 - XSS 防护:所有动态内容通过
escapeHtml() 转义 - 响应式设计:CSS Grid + Flexbox 布局
- 无障碍:使用
aria-label、aria-live、role 等属性 - 性能:ECharts 实例缓存在
charts{} 对象中,避免重复初始化
10.3 数据安全
- 管理员操作使用
@user_passes_test 权限检查
11. 数据字典
11.1 排放指标
11.2 AQI 等级划分
11.3 车辆结构指标
12. 扩展与维护指南
12.1 新增城市数据
- 在
views.py 的 CITY_COORDS 和 PROVINCE_COORDS 字典中添加坐标 - 准备 CSV 数据,确保列名与
COLUMN_MAP 一致 - 运行
python manage.py import_emissions 导入
12.2 新增图表
- 在
dashboard/urls.py 中注册路由 - 在
dashboard.js 中添加渲染函数和页面加载逻辑
12.3 新增分析维度
- 执行
python manage.py makemigrations && python manage.py migrate - 更新
import_emissions.py 的 COLUMN_MAP
12.4 预测模型升级
当前使用简单线性回归,可扩展为:
- XGBoost / LightGBM(多特征回归)
扩展位置:views.py 的 api_prediction() 函数。