158-基于FLask的风电场风力发电数据分析可视化
风电场风力发电数据分析可视化系统 — 技术文档
版本: 1.0 | 更新日期: 2026-06-21
1. 项目概述
基于 Flask 的风电场数据分析可视化平台,对 2019 年全年 35,040 条(15 分钟间隔)风电场运行数据进行多维分析、异常检测、产能效率评估和功率预测。
技术栈: Flask + SQLAlchemy + SQLite + ECharts 5.4.3 + NumPy + Pandas
代码规模: 6 个 Python 源文件(约 1,670 行)、19 个 HTML 模板(约 2,300 行)、1 个 CSS 文件(792 行),总计约 4,855 行。
2. 系统架构
┌─────────────────────────────────────────────────────────┐ │ 浏览器 (ECharts) │ ├─────────────────────────────────────────────────────────┤ │ Flask 路由层 (app.py) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │ 认证路由 │ │ 页面路由 │ │ 分析API │ │ 管理API │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘ │ │ │ │ │ │ │ │ ┌────▼─────────────▼─────────────▼──────────────▼────┐ │ │ │ SQLAlchemy ORM + NumPy │ │ │ └────────────────────┬───────────────────────────────┘ │ │ │ │ │ ┌────────────────────▼───────────────────────────────┐ │ │ │ SQLite (wind_farm.db) │ │ │ │ users 表 + wind_data 表 (35,040 行) │ │ │ └────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘数据流:
CSV (风电场_2019.csv) → init_db.py 批量导入 → SQLite → Flask API (SQL GROUP BY / NumPy 计算) → JSON → 前端 ECharts 渲染3. 目录结构
cloud/ ├── app.py # 主应用:所有路由和 API 逻辑 (1418 行) ├── models.py # SQLAlchemy 数据模型 (76 行) ├── config.py # 应用配置 (9 行) ├── init_db.py # 数据库初始化 + CSV 导入 (72 行) ├── requirements.txt # Python 依赖 ├── wind_farm.db # SQLite 数据库 (11 MB) ├── 风电场_2019.csv # 原始数据 (35,040 行, 3.9 MB) ├── utils/ │ ├── __init__.py │ └── prediction.py # 预测工具函数 (97 行) ├── templates/ │ ├── base.html # 基础布局 (侧边栏、顶栏、加载动画) │ ├── login.html # 登录页 │ ├── register.html # 注册页 │ ├── index.html # 数据总览仪表盘 │ ├── profile.html # 个人中心 │ ├── analysis_wind_speed.html # 风速分析 │ ├── analysis_wind_direction.html # 风向分析 │ ├── analysis_power.html # 功率分析 │ ├── analysis_meteorological.html # 气象分析 │ ├── analysis_time_series.html # 时序分析 │ ├── analysis_correlation.html # 相关性分析 │ ├── analysis_advanced.html # 高级图表 (10 种) │ ├── prediction.html # 功率预测 │ ├── anomaly_detection.html # 异常检测 │ ├── comparison.html # 月度对比 │ ├── production_efficiency.html # 产能效率分析 │ ├── data_manage.html # 数据管理 (admin) │ └── user_manage.html # 用户管理 (admin) └── static/ ├── css/style.css # 暗色主题样式 (792 行) └── img/wind-farm-bg.jpg # 登录页背景图4. 数据库设计
4.1 用户表users
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INTEGER | PK, 自增 | 用户 ID |
| username | VARCHAR(80) | UNIQUE, NOT NULL | 用户名 |
| password_hash | VARCHAR(256) | NOT NULL | Werkzeug 加密后的密码 |
| VARCHAR(120) | 邮箱 | ||
| phone | VARCHAR(20) | 手机号 | |
| avatar | VARCHAR(256) | DEFAULT ‘’ | 头像 (emoji) |
| role | VARCHAR(20) | DEFAULT ‘user’ | 角色: user / admin |
| created_at | DATETIME | DEFAULT NOW | 注册时间 |
4.2 风电数据表wind_data
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER (PK) | 记录 ID |
| timestamp | DATETIME (INDEXED) | 时间戳,15 分钟间隔 |
| wind_speed_10m | FLOAT | 10 米高度风速 (m/s) |
| wind_speed_30m | FLOAT | 30 米高度风速 (m/s) |
| wind_speed_50m | FLOAT | 50 米高度风速 (m/s) |
| wind_speed_70m | FLOAT | 70 米高度风速 (m/s) |
| wind_speed_hub | FLOAT | 轮毂高度风速 (m/s) |
| wind_dir_10m | FLOAT | 10 米高度风向 (°) |
| wind_dir_30m | FLOAT | 30 米高度风向 (°) |
| wind_dir_50m | FLOAT | 50 米高度风向 (°) |
| wind_dir_70m | FLOAT | 70 米高度风向 (°) |
| wind_dir_hub | FLOAT | 轮毂高度风向 (°) |
| temperature | FLOAT | 温度 (°C) |
| pressure | FLOAT | 气压 (hPa) |
| humidity | FLOAT | 湿度 (%) |
| power | FLOAT | 实际发电功率 (MW) |
4.3 数据库索引
CREATEINDEXidx_wind_timestampONwind_data(timestamp);CREATEINDEXidx_wind_power_tsONwind_data(timestamp,power);CREATEINDEXidx_wind_speed_tsONwind_data(timestamp,wind_speed_hub);idx_wind_timestamp: 支持所有时间范围查询和 ORDER BYidx_wind_power_ts: 覆盖索引,功率查询无需回表idx_wind_speed_ts: 覆盖索引,风速查询无需回表
5. API 接口文档
5.1 统一响应格式
// 成功{"code":0,"data":{...}}// 错误{"code":1,"msg":"错误信息"}// 分页{"code":0,"data":[...],"total":35040,"page":1,"limit":20}5.2 认证接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET/POST | /login | 登录,支持 JSON 和表单 |
| GET/POST | /register | 注册,首个用户自动成为 admin |
| GET | /logout | 退出登录 |
| GET/POST | /profile | 个人信息编辑(头像、邮箱、手机号、密码) |
认证方式:Session-based,使用werkzeug.security的generate_password_hash/check_password_hash。
5.3 仪表盘
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/dashboard/summary | 总览统计 |
返回字段:total_records,date_range,avg_power,max_power,total_energy,avg_speed,avg_temp
5.4 分析接口
所有分析接口支持?month=YYYY-MM参数筛选月份。
/api/analysis/wind_speed— 风速分析
{"monthly_avg":{"1":{"hub":5.32,"10m":4.10,"30m":4.85,"50m":5.12,"70m":5.45}},"frequency":{"labels":["0-1","1-2",...],"values":[2.1,5.3,...]},"time_series":{"timestamps":[...],"hub":[...],"10m":[...],"70m":[...]},"stats":{"hub_avg":6.28,"hub_max":18.5,"hub_min":0.0,"hub_std":3.41}}/api/analysis/wind_direction— 风向分析
{"rose":{"labels":["N","NNE",...],"frequency":{"N":8.5,...},"avg_speed":{"N":5.2,...}},"monthly_rose":{"1":{"N":12.3,...},"2":{...}},"heights":{"10m":{"N":10.2,...},"hub":{"N":8.5,...}}}/api/analysis/power— 功率分析
{"curve":{"labels":["0-1","1-2",...],"values":[0.0,0.5,...]},"monthly_avg":{"1":45.2,"2":52.1,...},"monthly_sum":{"1":33450.0,...},"distribution":{"labels":["0.0-10.0",...],"values":[1200,...]},"time_series":{"timestamps":[...],"power":[...],"wind_speed":[...]},"daily_energy":{"dates":["2019-01-01",...],"values":[2850.5,...]},"stats":{"avg_power":48.5,"max_power":198.2,"total_energy":425000.0,"capacity_factor":24.3}}/api/analysis/meteorological— 气象分析
返回月度均值、散点数据(温度-功率、湿度-功率、气压-功率)、时间序列、统计值。
/api/analysis/time_series— 时序分析
支持?agg=hour|day|week|month参数,返回聚合后的时间序列和自相关系数(滞后 1-48)。
/api/analysis/correlation— 相关性分析
返回 10×10 相关系数矩阵和两组散点数据(轮毂风速-功率、温度-功率)。
/api/analysis/advanced— 高级图表
一次返回 10 种图表数据:漏斗图、桑基图、河流图(堆叠柱状图)、箱线图、气泡图、季节小时模式、月度风玫瑰、累计发电量曲线、热力图、风速持续曲线。
/api/prediction— 功率预测
{"power_curve":{"speeds":[0,1,...,25],"powers":[0.0,0.5,...]},"monthly":{"1":{"avg_speed":5.32,"avg_power":45.2,"total_power":33450.0}},"daily_forecast":{"historical_dates":[...],"historical_values":[...],"forecast_values":[...]},"hourly_pattern":{"0":32.1,"1":28.5,...,"23":35.2},"weibull":{"labels":["0-1","1-2",...],"values":[2.1,5.3,...]}}5.5 数据洞察接口
/api/data/quality— 产能效率分析
基于贝茨极限(Betz Limit, Cp=16/27)计算理论最大发电量,与实际发电量对比:
- 转换效率 = 实际功率 / 理论功率 × 100%
- 容量因子 = 实际发电量 / (额定功率 × 运行小时数) × 100%
- 损失电量 = 理论发电量 - 实际发电量
物理参数:空气密度 ρ=1.225 kg/m³,叶轮半径 R=40m,额定功率 200MW。
/api/anomaly/detection— 异常检测
使用 IQR(四分位距)方法:
Q1, Q3 = np.percentile(values, [25, 75]) IQR = Q3 - Q1 异常范围: < Q1 - 1.5×IQR 或 > Q3 + 1.5×IQR分别检测风速、功率、温度三个维度的异常值,返回时间线和分布数据。
/api/comparison— 月度对比
返回月度发电量、风速、功率对比数据及环比变化率,标识最佳/最差月份。
5.6 管理接口
| 方法 | 路径 | 说明 | 权限 |
|---|---|---|---|
| GET | /api/data/list?page=1&limit=20&month=2019-03 | 分页数据列表 | admin |
| POST | /api/data/delete/<id> | 删除记录 | admin |
| POST | /api/data/update/<id> | 更新记录 | admin |
| GET | /api/user/list | 用户列表 | admin |
| POST | /api/user/add | 添加用户 | admin |
| POST | /api/user/update/<id> | 更新用户 | admin |
| POST | /api/user/delete/<id> | 删除用户 | admin |
| GET | /api/export/csv?month=2019-03 | CSV 导出 | login |
6. 核心算法
6.1 功率曲线预测
使用 3 次多项式拟合风速-功率关系:
coeffs=np.polyfit(wind_speeds,powers,3)poly=np.poly1d(coeffs)predicted=poly(predict_speeds)predicted[predicted<0]=0# 负值截断6.2 风速频率分布(类 Weibull)
bins=np.arange(0,max_speed+bin_size,bin_size)hist,edges=np.histogram(wind_speeds,bins=bins)frequency=hist/len(wind_speeds)*100# 百分比6.3 功率曲线(分箱均值)
bin_indices=np.digitize(wind_speeds,bins)foriinrange(len(bins)):mask=bin_indices==i curve[i]=np.mean(powers[mask])ifmask.any()else06.4 加权移动平均预测
val=0.5*recent[-1]+0.3*recent[-2]+0.2*recent[-3]基于最近 14 天数据,滑动窗口向前预测 7 天。
6.5 IQR 异常检测
q1,q3=np.percentile(values,[25,75])iqr=q3-q1 outliers=(values<q1-1.5*iqr)|(values>q3+1.5*iqr)6.6 自相关分析
forlaginrange(1,49):corr=np.corrcoef(speeds[:-lag],speeds[lag:])[0,1]用于检测风速的时间周期性。
6.7 产能效率(贝茨极限)
P_theoretical=0.5× ρ × A × v³ × Cp/10⁶# MW# ρ = 1.225 kg/m³, A = π × 40² m², Cp = 16/27efficiency=P_actual/P_theoretical ×100%capacity_factor=E_actual/(P_rated × hours)×100%7. 前端设计
7.1 配色方案
深色数据分析主题,主色调为琥珀金:
| 变量 | 色值 | 用途 |
|---|---|---|
--bg-primary | #0c0f14 | 页面背景 |
--bg-card | #1a1f2b | 卡片背景 |
--accent-primary | #f59e0b | 主色调(琥珀金) |
--accent-green | #10b981 | 正向数据 |
--accent-red | #ef4444 | 负向/异常 |
--accent-teal | #14b8a6 | 辅助色 |
--text-primary | #e8eaed | 主文本 |
--text-secondary | #9aa0ad | 次文本 |
7.2 图表技术
- ECharts 5.4.3(CDN 引入)
- 图表类型:折线图、柱状图、面积图、雷达图、玫瑰图、散点图、箱线图、桑基图、漏斗图、河流图、热力图、持续曲线
- 所有图表支持响应式 resize
- 加载时显示骨架屏 shimmer 动画
7.3 布局结构
┌──────────┬──────────────────────────────┐ │ │ 页面标题栏 │ │ 侧边栏 ├──────────────────────────────┤ │ (240px) │ │ │ │ 页面内容区 │ │ 导航菜单 │ (卡片网格 / 图表容器) │ │ │ │ │ │ │ │ 用户信息 ├──────────────────────────────┤ └──────────┴──────────────────────────────┘响应式断点:768px 以下侧边栏隐藏,图表网格变为单列。
8. 用户角色与权限
| 功能 | 普通用户 (user) | 管理员 (admin) |
|---|---|---|
| 查看仪表盘 | ✓ | ✓ |
| 所有分析页面 | ✓ | ✓ |
| 功率预测 | ✓ | ✓ |
| 个人中心 | ✓ | ✓ |
| 数据管理(CRUD) | ✗ | ✓ |
| 用户管理(CRUD) | ✗ | ✓ |
| CSV 导出 | ✓ | ✓ |
首个注册用户自动成为管理员(migrate_db()中实现)。
9. 数据处理流程
9.1 数据导入
风电场_2019.csv (UTF-8-BOM) ↓ pandas read_csv(encoding='utf-8-sig') ↓ 列名映射(中文→英文) ↓ 时间戳解析 ('%Y/%m/%d %H:%M') ↓ bulk_save_objects (1000条/批) ↓ wind_farm.db (35,040 行)9.2 查询优化策略
| 场景 | 策略 | 示例 |
|---|---|---|
| 月度/日度/小时聚合 | SQL GROUP BY | strftime('%m', timestamp)+.group_by() |
| 时间范围筛选 | 半开区间[start, end) | _month_filter()辅助函数 |
| 大数据量展示 | 尾部截取 500 点 | records[-500:] |
| 散点图数据 | 等步长采样 | data[::max(1, len(data)//500)] |
| 缺失值标记 | 哨兵值过滤 | > -50阈值,SQL 和 Python 双层过滤 |
9.3 能量计算
INTERVAL_HOURS=0.25# 15 分钟间隔energy_MWh=sum(power)×0.2510. 部署与运行
10.1 环境要求
- Python 3.11+
- 依赖:Flask 3.0.0, Flask-SQLAlchemy 3.1.1, Werkzeug 3.0.1, pandas 2.1.4, numpy 1.26.2
10.2 启动步骤
# 1. 安装依赖pipinstall-rrequirements.txt# 2. 初始化数据库(首次运行)python init_db.py# 3. 启动应用python app.py# 访问 http://127.0.0.1:500110.3 数据库迁移
app.py中的migrate_db()在启动时自动执行:
- 检查
users表是否有role列,无则添加 - 创建
wind_data表的三个索引 - 首个用户自动设为 admin
11. 已知限制
- SQLite 单写锁:并发写入时会排队,适合单用户或低并发场景
- scikit-learn 未使用:
requirements.txt中列出但代码未引用,可移除 - User.to_dict() 重复定义:
models.py中有两个同名方法,第二个覆盖第一个 - predict_monthly_power() 未使用:
utils/prediction.py中定义但从未调用 - 硬编码物理参数:贝茨极限计算中的叶轮半径(40m)和额定功率(200MW)为假设值
- 单年数据:仅包含 2019 年数据,无法做跨年同比分析
