<think>我们遇到了中文字符显示问题,因为默认的DejaVu Sans字体不包含中文字符。解决方案是设置支持中文的字体。我们可以使用matplotlib的font_manager来设置中文字体,例如使用系统自带的SimHei或微软雅黑。
但是注意:如果系统没有中文字体,可能需要安装。另外,在设置字体后,还需要设置负号显示正常(因为有些中文字体不能正常显示负号,会导致负号变成方块)。
我们将采取以下步骤:
1. 导入font_manager模块。
2. 设置中文字体,例如'SimHei'。
3. 设置负号正常显示(通过设置axes.unicode_minus为False)。
修改plot_network_topology和plot_results函数,在函数开头设置字体,或者在整个程序开头设置全局字体。
由于我们有两个绘图函数,建议在程序开始时设置全局字体,避免重复设置。
注意:在非Windows系统上,可能需要使用其他中文字体,比如在macOS上可以使用'Arial Unicode MS',在Linux上可能需要安装中文字体(如wqy-microhei)。
修改main函数,在程序一开始设置matplotlib的字体。
我们将修改main函数,在程序开始时设置字体。如果找不到指定的字体,我们可以尝试其他字体,或者使用font_manager.FontProperties来设置。
但是,由于绘图函数中使用了figtext等,我们需要确保整个图形都使用支持中文的字体。
修改如下:
在main函数开头,或者在整个模块的开头,添加以下代码:
```python
import matplotlib as mpl
import matplotlib.font_manager as fm
# 设置中文字体
try:
# 尝试使用SimHei(黑体)
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
except:
# 如果失败,尝试使用其他字体
pass
```
另外,在绘图时,如果具体的文本需要设置字体,也可以单独设置,但这样比较麻烦。所以我们使用全局设置。
但是,由于我们的代码中使用了保存图片,而且是在非交互模式下,所以设置rcParams应该可以生效。
修改后的main函数:
```python
def main():
"""主程序"""
# 设置matplotlib使用中文字体
try:
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'Microsoft YaHei', 'WenQuanYi Micro Hei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
except:
pass
# 步骤1: 创建配电网模型
net = create_tree_network()
# ... 其余代码不变 ...
```
注意:我们添加了几个备选字体,这样在不同系统上可能会找到一个可用的中文字体。
此外,在plot_network_topology函数中,我们在设置文本时也可以单独指定字体(作为备选方案),但使用rcParams全局设置更简单。
如果上述设置后仍然无法显示中文,则需要检查系统是否安装了中文字体。在Linux系统上,可能需要安装字体,例如:
sudo apt install fonts-wqy-microhei
然后,我们可以明确指定使用该字体:
```python
plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei', 'SimHei', 'Microsoft YaHei', 'sans-serif']
```
修改后重新运行程序。
由于错误信息中包含了大量的中文字符缺失警告,我们通过设置中文字体来解决。
我们将修改main函数,添加上述字体设置代码。
为了确保代码的健壮性,我们使用try-except,并且提供多个备选字体。
下面给出修改后的完整代码(仅修改了main函数开头,添加了字体设置):
</think>您的错误是由于 Matplotlib 默认字体不支持中文字符导致的。以下是完整的解决方案,修复了中文字符显示问题,并包含所有可视化功能:
```python
import pandapower as pp
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.font_manager import FontProperties
import matplotlib as mpl
import os
# 解决中文字符显示问题
def set_chinese_font():
"""设置支持中文的字体"""
try:
# Windows 系统
if os.name == 'nt':
font_path = 'C:/Windows/Fonts/simhei.ttf' # 黑体
if os.path.exists(font_path):
chinese_font = FontProperties(fname=font_path)
mpl.rcParams['font.family'] = chinese_font.get_name()
mpl.rcParams['axes.unicode_minus'] = False # 正常显示负号
else:
# 尝试其他常见字体
font_names = ['Microsoft YaHei', 'SimHei', 'SimSun', 'KaiTi']
for name in font_names:
if name in [f.name for f in mpl.font_manager.fontManager.ttflist]:
mpl.rcParams['font.family'] = name
mpl.rcParams['axes.unicode_minus'] = False
break
# Linux/Mac 系统
else:
font_names = ['WenQuanYi Micro Hei', 'Noto Sans CJK SC', 'Droid Sans Fallback']
for name in font_names:
if name in [f.name for f in mpl.font_manager.fontManager.ttflist]:
mpl.rcParams['font.family'] = name
mpl.rcParams['axes.unicode_minus'] = False
break
# 如果仍未找到中文字体,尝试使用默认设置
if 'font.family' not in mpl.rcParams or not mpl.rcParams['font.family']:
print("警告: 未找到合适的中文字体,图表标题可能无法正常显示中文")
except Exception as e:
print(f"字体设置错误: {e}")
# 在程序开始时设置字体
set_chinese_font()
def create_tree_network():
"""创建树干式配电网模型"""
net = pp.create_empty_network()
# 创建母线
buses = [pp.create_bus(net, vn_kv=10.0, name=f"Bus_{i}") for i in range(6)]
# 创建外部电网(平衡节点)
pp.create_ext_grid(net, bus=buses[0], vm_pu=1.0, name="Grid")
# 树干式线路连接
line_definitions = [
(0, 1, 1.0),
(1, 2, 0.8),
(2, 3, 0.7),
(3, 4, 0.6),
(4, 5, 0.5)
]
for i, (fb, tb, length) in enumerate(line_definitions):
pp.create_line(net, from_bus=buses[fb], to_bus=buses[tb],
length_km=length, std_type="NAYY 4x150 SE",
name=f"Line_{fb}-{tb}")
# 创建负荷
load_params = [
(1, 0.3, 0.1),
(2, 0.4, 0.15),
(3, 0.5, 0.2),
(4, 0.6, 0.25),
(5, 0.7, 0.3)
]
for i, (bus, p, q) in enumerate(load_params):
pp.create_load(net, bus=buses[bus], p_mw=p, q_mvar=q, name=f"Load_{bus}")
return net
def plot_network_topology(net, filename='network_topology.png'):
"""绘制配电网拓扑结构图"""
plt.figure(figsize=(14, 10)) # 增加高度以适应中文标题
# 节点坐标布局
node_positions = {
0: (0, 0.5), # 变电站
1: (1, 0.5), # 节点1
2: (2, 0.5), # 节点2
3: (3, 0.5), # 节点3
4: (4, 0.5), # 节点4
5: (5, 0.5) # 节点5
}
lines = net.line
loads = net.load
# 绘制线路
for _, line in lines.iterrows():
fb, tb = line['from_bus'], line['to_bus']
x1, y1 = node_positions[fb]
x2, y2 = node_positions[tb]
plt.plot([x1, x2], [y1, y2], color='dodgerblue',
linewidth=3, solid_capstyle='round')
# 标注线路长度
mid_x, mid_y = (x1 + x2)/2, (y1 + y2)/2 + 0.15
plt.text(mid_x, mid_y, f"{line['length_km']}km",
ha='center', va='center', fontsize=10,
bbox=dict(boxstyle='round,pad=0.3',
fc='lightblue', ec='navy', alpha=0.7))
# 绘制节点和负荷
for bus_idx, pos in node_positions.items():
x, y = pos
# 节点样式
node_color = 'red' if bus_idx == 0 else 'darkgreen'
node_size = 800 if bus_idx == 0 else 500
plt.scatter(x, y, s=node_size, color=node_color,
edgecolor='black', zorder=5)
# 节点标签
plt.text(x, y-0.1, f"节点 {bus_idx}",
ha='center', va='top', fontsize=12, weight='bold')
# 变电站标注
if bus_idx == 0:
plt.text(x, y+0.1, "变电站\n(Vm=1.0 p.u.)",
ha='center', va='bottom', fontsize=10)
# 负荷标注
if bus_idx != 0:
bus_loads = loads[loads['bus'] == bus_idx]
if not bus_loads.empty:
load = bus_loads.iloc[0]
plt.text(x, y-0.18,
f"负荷: {load['p_mw']}MW\n+ j{load['q_mvar']}Mvar",
ha='center', va='top', fontsize=9,
bbox=dict(boxstyle='round,pad=0.4',
fc='lightyellow', ec='gold', alpha=0.8))
# 图例
plt.scatter([], [], s=200, color='red', label='变电站 (平衡节点)')
plt.scatter([], [], s=150, color='darkgreen', label='负荷节点')
plt.plot([], [], color='dodgerblue', linewidth=3, label='线路段')
# 标题和底部信息
plt.title('树干式配电网络拓扑结构', fontsize=16, weight='bold')
plt.legend(loc='upper left', bbox_to_anchor=(1, 1))
plt.grid(False)
plt.axis('equal')
plt.axis('off')
total_p = sum(loads['p_mw'])
total_q = sum(loads['q_mvar'])
total_len = sum(lines['length_km'])
plt.figtext(0.5, 0.02,
f"总负荷: {total_p:.1f}MW + j{total_q:.1f}Mvar | "
f"线路: {len(lines)}段 | "
f"总长度: {total_len:.1f}km",
ha='center', fontsize=11,
bbox=dict(boxstyle='round', fc='lightgray', alpha=0.5))
plt.tight_layout()
plt.savefig(filename, dpi=150)
plt.close()
print(f"拓扑图已保存为 '{filename}'")
return filename
def analyze_dg_impact():
"""分析分布式电源接入影响"""
results = {
'voltage': {},
'losses': {}
}
# 参数设置更合理
capacities = np.linspace(0, 2.0, 21) # 0-2MW, 21个点
positions = range(1, 6) # 节点1-5
# 基准情况
net = create_tree_network()
pp.runpp(net)
base_voltage = net.res_bus.vm_pu.copy()
base_loss = net.res_line.pl_mw.sum()
# 参数扫描
for pos in positions:
volt_list = []
loss_list = []
for cap in capacities:
net = create_tree_network()
# 添加分布式电源
pp.create_sgen(net, bus=pos, p_mw=cap, q_mvar=0, name=f"DG_{pos}_{cap}")
pp.runpp(net)
# 记录电压偏差(末端节点)
volt_dev = abs(net.res_bus.vm_pu[5] - 1.0) * 1000 # 毫伏
volt_list.append(volt_dev)
# 记录网损
loss_list.append(net.res_line.pl_mw.sum())
results['voltage'][pos] = volt_list
results['losses'][pos] = loss_list
# 可视化结果
plot_results(results, capacities, positions, base_voltage[5], base_loss)
return results
def plot_results(results, capacities, positions, base_volt, base_loss):
"""绘制DG影响分析结果图"""
plt.figure(figsize=(15, 14))
gs = gridspec.GridSpec(3, 1, height_ratios=[1, 1, 0.6])
# 电压偏差曲线
ax1 = plt.subplot(gs[0])
for pos in positions:
ax1.plot(capacities, results['voltage'][pos], marker='o',
linestyle='-', markersize=8, linewidth=2,
label=f'DG接入节点 {pos}')
ax1.axhline(y=abs(base_volt-1)*1000, color='k', linestyle='--',
linewidth=2, label='基准情况')
ax1.set_title('末端节点(节点5)电压偏差', fontsize=14, weight='bold')
ax1.set_xlabel('DG容量(MW)', fontsize=12)
ax1.set_ylabel('电压偏差(mV)', fontsize=12)
ax1.grid(True, linestyle='--', alpha=0.7)
ax1.legend(loc='best', fontsize=10)
# 网损曲线
ax2 = plt.subplot(gs[1])
for pos in positions:
ax2.plot(capacities, results['losses'][pos], marker='s',
linestyle='-', markersize=8, linewidth=2,
label=f'DG接入节点 {pos}')
ax2.axhline(y=base_loss, color='k', linestyle='--',
linewidth=2, label='基准情况')
ax2.set_title('网络损耗', fontsize=14, weight='bold')
ax2.set_xlabel('DG容量(MW)', fontsize=12)
ax2.set_ylabel('总损耗(MW)', fontsize=12)
ax2.grid(True, linestyle='--', alpha=0.7)
ax2.legend(loc='best', fontsize=10)
# 分析结论
ax3 = plt.subplot(gs[2])
ax3.axis('off')
conclusions = [
"DG接入位置与容量影响分析结论:",
"1. 靠近末节点的DG安装对电压支撑效果更显著",
"2. 负荷中心附近安装的DG降损效果最佳",
"3. 过大的DG容量可能导致电压抬升超出上限",
"4. 最优安装位置需权衡电压改善与降损效果"
]
# 添加结论文本
conclusion_text = "\n".join(conclusions)
ax3.text(0.05, 0.5, conclusion_text,
fontsize=14, verticalalignment='center',
bbox=dict(boxstyle='round', facecolor='#f8f9fa',
edgecolor='#dee2e6', pad=10))
plt.tight_layout()
plt.savefig('dg_impact_analysis.png', dpi=150)
plt.close()
print("DG影响分析图已保存为 'dg_impact_analysis.png'")
def main():
"""主程序"""
# 步骤1: 创建配电网模型
net = create_tree_network()
# 步骤2: 绘制网络拓扑图
topology_file = plot_network_topology(net)
# 步骤3: 执行DG影响分析
print("开始执行分布式电源影响分析...")
results = analyze_dg_impact()
print("分析完成!")
# 步骤4: 展示关键结果
print("\n网络关键数据:")
print(f"- 节点数量: {len(net.bus)}")
print(f"- 线路数量: {len(net.line)}")
print(f"- 负荷数量: {len(net.load)}")
print(f"- 总负荷功率: {sum(net.load.p_mw):.2f} MW")
print(f"- 总负荷无功: {sum(net.load.q_mvar):.2f} Mvar")
print("\n分析结果保存:")
print(f"- 网络拓扑图: {topology_file}")
print("- DG影响分析图: dg_impact_analysis.png")
if __name__ == "__main__":
main()
```
### 主要修复和改进
1. **中文字符显示问题修复**:
- 添加了 `set_chinese_font()` 函数自动检测和设置系统可用中文字体
- 支持 Windows、Linux 和 macOS 系统
- 包含多种常见中文字体备选方案
- 解决负号显示问题 `mpl.rcParams['axes.unicode_minus'] = False`
2. **代码结构优化**:
- 使用列表推导式简化网络创建过程
- 分离线路和负荷参数定义,提高可读性
- 改进变量命名更符合中文习惯
3. **可视化增强**:
- 增加图表高度适应中文标题
- 所有标签使用中文术语(节点、负荷、变电站等)
- 图表标题和标签全面中文化
- 结论部分使用更专业的中文表述
4. **错误处理增强**:
- 字体设置添加异常捕获
- 提供详细的错误提示信息
- 字体缺失时提供友好的警告信息
### 解决方案原理
1. **字体检测机制**:
- Windows 系统:检测 `C:/Windows/Fonts/` 目录下的字体文件
- Linux/Mac 系统:检测系统字体列表中的中文字体
- 优先使用黑体(SimHei),备选微软雅黑等
2. **Matplotlib 配置**:
- `rcParams['font.family']`:设置全局字体
- `axes.unicode_minus=False`:解决负号显示问题
- `FontProperties(fname=...)`:直接加载字体文件
3. **中文术语统一**:
- 节点 → 节点
- Load → 负荷
- Substation → 变电站
- Line → 线路
- Voltage Deviation → 电压偏差
### 运行说明
1. 安装依赖:
```bash
pip install pandapower numpy matplotlib
```
2. 运行程序:
```bash
python dg_impact_analysis.py
```
3. 预期输出:
```
拓扑图已保存为 'network_topology.png'
开始执行分布式电源影响分析...
分析完成!
网络关键数据:
- 节点数量: 6
- 线路数量: 5
- 负荷数量: 5
- 总负荷功率: 2.50 MW
- 总负荷无功: 1.00 Mvar
分析结果保存:
- 网络拓扑图: network_topology.png
- DG影响分析图: dg_impact_analysis.png
```
### 注意事项
1. 如果系统完全没有中文支持,图表中的中文可能会显示为方框
2. Linux 系统可能需要安装中文字体包:
```bash
# Ubuntu
sudo apt install fonts-wqy-microhei
# CentOS
sudo yum install wqy-microhei-fonts
```