很多电力行业新人,刚开始做数据分析时,会非常依赖 Excel 表格。
一张表几十行还好。
如果变成几百行、几千行,甚至一年 8760 小时的电价数据,问题就来了。
你盯着一列数字看半天,很难快速回答:
哪个时段电价最高?
负荷什么时候冲上去?
高价是不是集中在白天?
不同地区负荷差异大不大?
峰、平、谷、尖峰电价差异到底有多明显?
这时候,图表的价值就出来了。
因为图表能把“数字变化”变成“视觉变化”。
一条负荷曲线,可以告诉你一天的用电节奏。
一张电价走势图,可以告诉你价格什么时候抬升。
一张柱状图,可以告诉你不同分时电价时段的价格差异。
一张交互式图表,可以让你把鼠标放到某个点上,直接看到具体时间和价格。
所以,本章我们不追求复杂。
只做几张最实用的电力交易入门图表。
如果你平时拿到电价表、负荷表,只会在 Excel 里一行行看数字,这一章建议先收藏。
本章会用一份教学用模拟数据,生成:
负荷趋势图、电价走势图、地区负荷对比图、分时电价对比图、负荷与电价组合图,以及一张可以用鼠标查看具体数据的交互式图表。
文末我准备了第6章配套资料包,包括完整代码、模拟数据、PNG图表示例、交互式HTML图表、图表说明报告和可视化检查清单。
电力交易数据有一个特点:
强时间性。
电价会随着时间变化。
负荷会随着时间变化。
电量会按日、按月、按年累计。
分时电价会分成尖峰、峰、平、谷等不同时段。
现货价格通常具有较强时间颗粒度,可能按小时、15 分钟或其他规则颗粒度形成和披露,具体以当地市场规则和公开数据口径为准。
所以,电力数据非常适合可视化。
你可以先记住一个判断标准:
只要数据和时间有关,大概率就值得画成趋势图。
比如:
小时负荷数据,可以画负荷趋势图。
小时电价数据,可以画电价走势图。
不同地区负荷,可以画对比折线图。
峰、平、谷、尖峰价格,可以画分时电价对比图。
一个月电价变化,可以画交互式图表。
图表不是为了好看,而是为了更快发现问题。
但也要注意:图表只是辅助观察,不是最终结论。
比如:看到电价高,只能说“该时段在本样本中价格较高”。
不能直接说“该时段一定适合放电套利”。
看到负荷高,只能说“该时段负荷较高”。
不能直接说“该用户一定适合做储能”。
看到负荷曲线和电价曲线同步上升,也只能说明在图表上存在同步变化现象。
不能直接证明负荷导致电价上涨。
真实判断要结合规则、合同、成本、负荷特征、结算口径和项目参数。
第3章里,我们已经用 Matplotlib 画过简单的电价趋势图。
本章会稍微升级一下。
Matplotlib 是 Python 里非常常用的静态绘图库。
这一章我们会用它做几件事:
添加标题。
添加横轴和纵轴名称。
添加图例。
添加网格线。
保存图片。
让图表更适合放进文章、报告或学习笔记里。

负荷趋势图适合回答:
一天中什么时候用电多?什么时候用电少?有没有明显高峰?是不是夜间负荷很低?有没有晚高峰?
对工商业用户来说,负荷曲线很重要。
因为它可能和这些问题有关:
生产班次、空调负荷、设备集中启动、最大需量、储能削峰、需求响应、用电成本优化。
但注意:
负荷趋势图只能告诉你“负荷什么时候高、什么时候低”。而是否适合做储能,还需要结合:电价机制、最大需量或容量电费、负荷持续时间、储能功率和容量、充放电效率、投资成本、并网条件、交易规则、结算口径。这些都不是一张图能直接回答的。
电价走势图适合回答:
电价什么时候低?什么时候高?高价是否集中在某些时段?是否存在明显波动?不同价格时段之间差异是否值得关注?
*需要特别提醒:图表只能帮助观察价格变化,不能直接得出交易结论。比如:电价高,不等于一定能套利。电价低,也不等于一定适合充电。真实业务还要结合市场规则、结算口径、负荷曲线、交易权限、项目参数和风险约束。
只看一条曲线,能看趋势。
但真实分析中,我们经常需要对比。
比如:
A 地区和 B 地区的负荷走势有什么不同?峰、平、谷、尖峰电价差异有多大?白天和夜间用电差异明显吗?不同区域是否存在负荷高峰错位?
这时候就要做多维度可视化。
本章会做两类图:
第一类:地区负荷对比图。
第二类:分时电价对比图。

假设我们有两个地区:
华北示例区。
华东示例区。
它们在同一天的负荷变化不同。
把两条负荷曲线放在同一张图里,就能直观看出:
哪个地区负荷更高。
哪个地区晚高峰更明显。
两个地区负荷变化节奏是否一致。
*注意:本章地区名称只是教学示例,不代表真实行政区,不代表真实电网区域,不代表真实华北、华东区域负荷数据。
分时电价对比图适合用柱状图。
比如本章教学模拟数据中设置:
谷段电价:0.35 元/kWh。
平段电价:0.65 元/kWh。
峰段电价:0.95 元/kWh。
尖峰电价:1.20 元/kWh。
画成柱状图以后,读者能很直观地看到:
哪个时段最贵。
哪个时段最便宜。
尖峰、峰、平、谷之间差异有多大。
*本章使用的是教学用模拟分时电价。真实峰、平、谷、尖峰时段和价格,需要根据所在省份、用户类别、电压等级、用电性质、最新分时电价政策、供电公司公告以及用户实际合同结算口径核验,不能直接套用本章示例。
Matplotlib 适合做静态图。
静态图适合放在公众号、报告、PPT、Word 文档里。
但有时候,我们希望图表能拖动、缩放、悬停查看数据点。
这时候可以用 Plotly。
Plotly 可以用来生成交互式图表。
本章用 Plotly 做一张交互式电价图。
运行后会生成一个:
interactive_price_chart.html你可以用浏览器打开。
打开后,可以:
拖动图表。缩放时间范围。鼠标悬停查看具体电价。查看对应时段类型和负荷。
这类图表很适合做内部分析、培训演示和自用数据探索。
本章目标是让零基础读者完成一个明确成果:
用 Python 自动生成一份简单的电力交易数据可视化报告。
这份报告包括:
负荷趋势图、电价走势图、地区负荷对比图、分时电价对比图、负荷与电价组合图、交互式电价图、图表说明文本报告。
这不是复杂的商业分析报告。而是一份入门版可视化报告模板。
先跑通。再理解。最后再逐步替换成自己的合规数据。
本章使用教学用模拟数据。
数据包含两个示例地区一天 24 小时的负荷和电价信息。
字段包括:
本章会自动创建一份 CSV 文件:
chapter06_visual_data.csv*本章数据为教学用模拟数据,不代表任何真实地区、真实用户、真实电价、真实现货价格或真实分时电价规则。
为了减少路径报错,建议把本章代码放在一个简单英文路径中,例如:
D:\python_power_trade\chapter06本章代码会自动在这个文件夹中创建和读取:
chapter06_visual_data.csv处理完成后,也会把所有图表和报告文件导出到同一个文件夹中。
本章需要安装 3 个库:
python -m pip install pandas matplotlib plotly如果 Windows 上 python 命令不生效,可以尝试:
py -m pip install pandas matplotlib plotly国内网络下载较慢时,可以使用:
python -m pip install pandas matplotlib plotly -i https://pypi.tuna.tsinghua.edu.cn/simple或者:
py -m pip install pandas matplotlib plotly -i https://pypi.tuna.tsinghua.edu.cn/simple请新建文件:
chapter06_power_visual_report.py第6章的目标只有一个:
把一份电力数据表,变成可以直接查看、保存和用于学习汇报的图表与报告。
你只需要先完整运行一次,确认代码能够生成 PNG 图片、交互式 HTML 图表和文字说明报告,再回头理解每一段代码。
你可以在文末私信关键词电力Python06领取本章资料包,里面已经准备好完整代码、模拟数据、图表示例和运行说明。
# -*- coding: utf-8 -*-这一行表示代码文件使用 UTF-8 编码。
现在大多数新版编辑器默认支持 UTF-8,所以这行通常不是必须的。
但对零基础读者来说,保留这一行可以减少少数电脑上中文乱码的概率。
from pathlib import Pathimport pandas as pdimport matplotlib.pyplot as pltimport plotly.express as px这里导入了四个工具。
pathlib:Python 自带的路径处理工具,用来帮助程序找到文件位置。
pandas:读取和处理表格数据。
matplotlib.pyplot:绘制静态图表。
plotly.express:绘制交互式图表。
本章里,你可以先把它们理解成:
Path 管文件路径。
Pandas 管数据。
Matplotlib 画静态图。
Plotly 画可交互图。
current_folder = Path(__file__).resolve().parent这行代码的意思是:
找到当前这个 Python 文件所在的文件夹。
为什么要这样写?
因为很多新手会遇到一个问题:
代码运行了,但不知道 CSV、图片、HTML、报告文件保存到哪里去了。
使用这一行代码后,程序会从“当前 Python 文件所在文件夹”去生成、读取和导出文件。
这样路径更稳定,也更容易找到结果。
data_file = current_folder / "chapter06_visual_data.csv"load_chart_file = current_folder / "chart01_daily_load_trend.png"price_chart_file = current_folder / "chart02_daily_price_trend.png"region_compare_file = current_folder / "chart03_regional_load_comparison.png"period_price_file = current_folder / "chart04_tou_price_comparison.png"combined_file = current_folder / "chart05_load_price_combined.png"interactive_file = current_folder / "interactive_price_chart.html"report_file = current_folder / "chapter06_visual_report.txt"这些代码表示:
所有输入和输出文件,都放在当前 Python 文件所在文件夹中。
也就是说,代码运行后,你应该能在同一个文件夹中看到:
chapter06_power_visual_report.pychapter06_visual_data.csvchart01_daily_load_trend.pngchart02_daily_price_trend.pngchart03_regional_load_comparison.pngchart04_tou_price_comparison.pngchart05_load_price_combined.pnginteractive_price_chart.htmlchapter06_visual_report.txt这样对新手更友好,不容易找不到文件。
ifnot data_file.exists():这行代码的意思是:
如果当前文件夹没有 chapter06_visual_data.csv,代码就自动创建一份教学用模拟数据。
这样做是为了降低新手门槛。
你不用手动准备数据,复制代码就能运行。
if0 <= hour <= 6: period_type = "谷" price = 0.35elif7 <= hour <= 10: period_type = "平" price = 0.65elif11 <= hour <= 17: period_type = "峰" price = 0.95elif18 <= hour <= 21: period_type = "尖峰" price = 1.20else: period_type = "平" price = 0.65这段代码模拟分时电价。
夜间是谷段,价格较低。
白天是峰段,价格较高。
晚间是尖峰,价格最高。
required_columns = ["datetime","region","load_mw","price_yuan_kwh","period_type",]for column in required_columns:if column notin df.columns:raise ValueError(f"CSV 文件中缺少必要字段:{column}")这段代码用于检查 CSV 文件是否包含本章需要的字段。
如果读者手动修改了 CSV 表头,比如把 load_mw 改成 load,程序会主动提示缺少哪个字段。
这样比直接出现 KeyError 更适合新手理解。
小白阶段建议先不要改字段名,先完整跑通示例代码。
df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")df["load_mw"] = pd.to_numeric(df["load_mw"], errors="coerce")df["price_yuan_kwh"] = pd.to_numeric(df["price_yuan_kwh"], errors="coerce")这几行代码分别做三件事:
把 datetime 转成 Python 可以识别的时间。
把 load_mw 转成数字。
把 price_yuan_kwh 转成数字。
为什么要这样做?
因为 CSV 文件中的内容看起来像数字,但实际可能被当成文本。
如果读者手动把负荷写成:
500MW约500或者把电价写成:
0.65元约0.65后面画图和计算就可能出错。
所以代码会先进行转换,并检查是否存在无法转换的内容。
print("\n数据行数:", len(df))print("\n缺失值检查:")print(df.isna().sum())print("\n地区列表:")print(df["region"].unique())print("\n时段类型列表:")print(df["period_type"].unique())这几行代码是在画图之前做基础检查。
这样做是为了延续第4章的数据清洗习惯:
先检查数据。
再画图。
不要一拿到数据就直接画图。
因为如果数据缺失、重复、字段错误,图表也会跟着错。
本章教学样本预期有:
24 小时 × 2 个示例地区 = 48 行所以代码中增加了:
expected_rows = 24 * 2if len(df) != expected_rows: print(f"\n提醒:当前数据行数为 {len(df)},教学样本预期为 {expected_rows} 行,请检查是否缺失或重复。")这可以提醒读者关注数据完整性。
region_record_count = df.groupby("region").size()print(region_record_count)for region_name, record_count in region_record_count.items():if record_count != 24: print(f"提醒:{region_name} 当前记录数为 {record_count},教学样本预期为 24 条。")这段代码会检查每个地区分别有多少条记录。
本章每个示例地区应该都有 24 条小时级记录。
如果某个地区少于 24 条,说明可能存在缺失。
如果某个地区多于 24 条,说明可能存在重复或额外数据。
这一步是为了帮助读者理解:
做可视化之前,也要检查样本是否完整。
region_map = {"华北示例区": "North Example","华东示例区": "East Example"}period_map = {"谷": "Valley","平": "Flat","峰": "Peak","尖峰": "Critical Peak"}很多新手运行 Matplotlib 时会遇到中文乱码。
比如中文标题变成方框。
中文图例显示不出来。
为了减少这类问题,本章静态图表尽量使用英文标签。
原始数据里仍然保留中文字段和中文地区名。
但画图时使用英文展示标签。
这样既保留了电力业务含义,也降低了新手报错概率。
target_region = "华北示例区"region_df = df[df["region"] == target_region].copy()if region_df.empty:raise ValueError(f"未找到目标地区:{target_region},请检查 region 字段。")这段代码表示:
本章先选择一个地区作为单地区图表的分析对象。
默认选择:
华北示例区如果你想改成华东示例区,可以把代码改成:
target_region = "华东示例区"如果目标地区不存在,程序会主动提示。
这样可以避免后面画图时因为数据为空而报错。
plt.plot( region_df["hour"], region_df["load_mw"], marker="o", label="Load")这段代码表示:
横轴是小时。
纵轴是负荷。
每个数据点用圆点标出来。
label="Load" 是图例名称。
后面的:
plt.title("Daily Load Trend")plt.xlabel("Hour")plt.ylabel("Load (MW)")plt.grid(True, linestyle="--", alpha=0.5)plt.legend()分别表示:
添加标题。
添加横轴名称。
添加纵轴名称。
添加网格线。
添加图例。
这些操作会让图表更适合放进报告。
最后:
plt.savefig(load_chart_file, dpi=150)plt.close()表示:
保存图片。
关闭图表对象。
本章不使用 plt.show() 强制弹窗,是为了避免新手遇到连续弹窗或程序卡住的问题。
plt.plot( region_df["hour"], region_df["price_yuan_kwh"], marker="o", label="Price")这段代码画的是电价曲线。
横轴仍然是小时。纵轴是电价。单位是元/kWh。
电价走势图适合看:
低价时段。高价时段。价格是否呈现明显分时差异。
for region_name in df["region_en"].unique(): temp_df = df[df["region_en"] == region_name] plt.plot( temp_df["hour"], temp_df["load_mw"], marker="o", label=region_name )这段代码的意思是:
把每个地区的数据分别取出来。
然后各画一条负荷曲线。
最后放在同一张图里。
这样就能直观对比不同地区的负荷水平和变化趋势。
period_price = region_df.groupby("period_type_en").agg( avg_price=("price_yuan_kwh", "mean")).reset_index()这段代码先按时段类型分组。
然后计算每类时段的平均电价。
比如:
谷段平均电价。
平段平均电价。
峰段平均电价。
尖峰平均电价。
然后用:
plt.bar( period_price["period_type_en"], period_price["avg_price"], label="Average Price")画成柱状图。
柱状图适合做类别对比。
在这里,它比折线图更适合展示谷、平、峰、尖峰之间的价格差异。
fig, ax1 = plt.subplots(figsize=(10, 5))这行代码创建了一张图。
然后:
ax1.plot(region_df["hour"], region_df["load_mw"])画负荷。
再用:
ax2 = ax1.twinx()ax2.plot(region_df["hour"], region_df["price_yuan_kwh"])创建第二个纵轴,用来画电价。

为什么要两个纵轴?
因为负荷单位是 MW。
电价单位是元/kWh。
两个指标单位不一样,数值量级也不一样。
如果硬放在同一个纵轴上,会很难看清。
所以使用双轴图。
但要特别注意:
双轴图只能辅助观察趋势同步性。不能直接比较两条线的高度。更不能用它证明负荷和电价存在因果关系。真实市场价格还会受到交易规则、供需结构、机组报价、新能源出力、输电约束和结算机制等因素影响。
fig_interactive = px.line( region_df, x="datetime", y="price_yuan_kwh", markers=True, title="Interactive Daily Price Trend", labels={"datetime": "Datetime","price_yuan_kwh": "Price (Yuan/kWh)" }, hover_data=["period_type", "load_mw"])这段代码使用 Plotly 生成交互式折线图。
它的好处是:
鼠标移动到数据点上,可以看到具体信息。可以放大某段时间。可以拖动查看不同区域。
最后:
fig_interactive.write_html(interactive_file)会把图表保存成 HTML 文件。
用浏览器打开即可查看。
运行代码后,会生成 8 个文件。
chapter06_visual_data.csv这是本章自动生成的教学用模拟数据。
包含两个示例地区一天 24 小时的负荷、电价和时段类型。
chart01_daily_load_trend.png用途:
观察单个地区一天内负荷变化。
你可以从图中看出:
夜间负荷较低。
白天负荷上升。
晚高峰负荷较高。
chart02_daily_price_trend.png用途:
观察一天内电价变化。
你可以从图中看出:
谷段电价较低。
峰段电价较高。
尖峰时段电价最高。
chart03_regional_load_comparison.png用途:
比较两个示例地区的负荷变化。
你可以用它观察:
哪个地区整体负荷更高。
两个地区高峰时段是否一致。
负荷曲线形态是否相似。
chart04_tou_price_comparison.png用途:
比较谷、平、峰、尖峰时段的平均电价。
这张图适合用于讲解分时电价展示方法。
但真实峰、平、谷、尖峰时段和价格,需要以当地最新政策、公告或合同结算口径为准。
chart05_load_price_combined.png用途:
同时观察负荷与电价变化。
需要注意:
负荷和电价单位不同,所以这张图使用双纵轴。
看图时应关注趋势,不要直接把两条线的高度放在一起比较。
也不要根据这张图直接判断因果关系。
interactive_price_chart.html用途:
用浏览器打开后,可以拖动、缩放、悬停查看数据。
适合做内部分析、培训演示或自用数据探索。
chapter06_visual_report.txt用途:
自动说明本章生成了哪些图,每张图适合看什么问题,并附带风险提示。
这一步的意义是:
不只是生成图片,而是让图表进入“报告表达”。
本章所有文件都会生成在当前 Python 文件所在文件夹中。
也就是和这个文件放在一起:
chapter06_power_visual_report.py你应该能在同一个文件夹中看到:
chapter06_visual_data.csvchart01_daily_load_trend.pngchart02_daily_price_trend.pngchart03_regional_load_comparison.pngchart04_tou_price_comparison.pngchart05_load_price_combined.pnginteractive_price_chart.htmlchapter06_visual_report.txt把代码中的:
price = 1.20改成:
price = 1.50重新运行代码。
观察分时电价对比图是否发生变化。
把华北示例区晚高峰负荷:
load_north = 880改成:
load_north = 1000重新运行代码。
观察负荷趋势图和地区负荷对比图是否变化。
把代码中的:
target_region = "华北示例区"改成:
target_region = "华东示例区"重新运行代码。
观察单地区负荷趋势图、电价走势图和组合图是否切换到新地区。
如果一个用户的负荷高峰和电价高峰高度重合,你会进一步分析什么?
可以从这些角度思考:
是否可以调整生产班次?
是否可以做需求响应?
是否存在削峰空间?
是否有储能配置价值?
是否需要结合 15 分钟负荷数据进一步判断?
是否需要核验电价类型和结算规则?
本章我们完成了从“数据表”到“图表报告”的入门练习。
你至少需要记住以下几点:
第一,电力交易数据具有强时间性,非常适合画趋势图。
第二,负荷趋势图可以帮助观察用电节奏。
第三,电价走势图可以帮助观察价格变化。
第四,地区负荷对比图可以帮助观察不同区域或不同用户之间的曲线差异。
第五,分时电价对比图可以帮助观察谷、平、峰、尖峰价格差异。
第六,交互式图表适合内部分析、培训演示和数据探索。
第七,双轴图只能辅助观察趋势,不能直接证明因果关系。
第八,图表不是结论,真实业务判断还需要规则、合同、结算口径和人工复核。
这章看起来是在讲画图。
但真正想让你建立的是一种表达能力:
把电力交易数据从“表格里的数字”,变成别人一眼能看懂的图表和报告。
这就是数据分析从“自己看懂”走向“别人也看懂”的关键一步。
如果你已经成功运行本章代码,并在文件夹中看到了 PNG 图表和 HTML 交互式图表,欢迎在评论区回复:
可视化报告已跑通
如果你想直接领取本章配套资料,可以私信公众号关键词:
电力Python06
领取《Python电力交易》第6章可视化资料包,包括:
chapter06_power_visual_report.py 完整代码chapter06_visual_data.csv 教学用模拟数据interactive_price_chart.html 交互式电价图chapter06_visual_report.txt 图表说明报告建议使用顺序:
先看运行说明 → 跑通完整代码 → 打开生成的PNG图片 → 查看交互式HTML图表 → 对照检查清单理解图表风险 → 尝试替换成自己的合规数据。
也欢迎你在评论区回答一个问题:
你最想优先用 Python 画哪类电力数据图表?
A. 用户负荷曲线
B. 工商业分时电价图
C. 现货电价走势图
D. 日前与实时价格对比图
E. 储能充放电曲线
F. 月度电费分析图
G. 多省电价对比图
*本章全部数据均为教学用模拟数据,仅用于演示 Python 可视化方法,不代表任何真实地区、真实用户、真实电价或真实交易规则。 图表只能辅助观察数据现象,不构成交易建议、售电报价建议、储能收益测算依据或经营决策依据。
点击阅读往期系列文章: