You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Matplotlib子图时Y轴范围与字体不一致的解决方法

解决子图Y轴范围波动与字体不一致问题

问题根源分析

1. Y轴范围持续变化

原代码存在两个核心问题导致Y轴范围不稳定:

  • 画布创建位置错误:在遍历每个通道的循环内创建fig,导致每个通道单独生成画布,而非在同一个画布中生成子图,根本没实现真正的子图布局。
  • Y轴范围未针对性控制:全局传入的ylim对所有子图生效,未根据不同电气参数的特性设置对应范围,也未提前统计数据的极值来固定范围。

2. 字体不一致

代码中分散设置了多种字体大小(如title_font、Y_font、X_font、刻度字体4、图例3.5),且未统一字体类型,同时部分文本元素的字体设置可能遗漏。


解决方案与修改后代码

关键调整点

  1. 将画布fig的创建移到通道分块(chunk)的循环内,确保同一个分块的所有通道在同一个画布生成子图。
  2. 提前读取当前分块所有通道的数据,统计每个通道的Y轴极值,用于固定范围;也支持传入针对单个通道的Y轴范围配置。
  3. 全局统一字体设置,通过plt.rcParams预设字体大小和类型,避免分散设置导致的不一致。

修改后的代码:

import glob
import os
import sys
import pandas as pd
import matplotlib.pyplot as plt

# 全局统一字体设置
plt.rcParams['font.size'] = 8
plt.rcParams['font.family'] = 'Arial'  # 可替换为你需要的字体

def Naming_Ylabels(chan_name):
    # 保留你原有的Y轴标签命名逻辑,示例如下
    if "FREQ" in chan_name:
        return "Frequency [Hz]"
    elif "VOLT" in chan_name:
        return "Voltage [kV]"
    else:
        return chan_name

def plot_subplots(Monitor_Channels, subTitle, **kwarg):
    outfiles = glob.glob(os.path.join(os.getcwd(), "PSSE_Data", "*.csv"))
    if not Monitor_Channels:
        print("No channels available to plot !")
        sys.exit()
    
    for outfile in outfiles:
        # 按每6个通道分块处理
        for k, j in enumerate(range(0, len(Monitor_Channels), 6)):
            chunk = Monitor_Channels[j:j+6]
            nrows = len(chunk)
            ncols_sub = 1 if nrows % 2 != 0 else 2
            
            # 先读取当前分块所有通道的数据,统计Y轴范围
            chunk_data = {}
            for chans in chunk:
                df = pd.read_csv(outfile, usecols=['Time', chans], index_col=False, header=0)
                t = df['Time'].values
                chan_data = df[chans].values
                if "FREQ" in chans:
                    chan_data = 50 * (1 + chan_data)
                chunk_data[chans] = (t, chan_data)
            
            # 创建单个画布,用于放置当前分块的所有子图
            fig_name = f"{os.path.basename(outfile[:-4])}{subTitle}"
            fig = plt.figure(fig_name, linewidth=0.5, figsize=(8, 12))
            fig.suptitle(os.path.basename(outfile[:-4]), fontsize=10, y=0.98)
            
            for n, chans in enumerate(chunk):
                t, chan_data = chunk_data[chans]
                # 创建子图
                ax = plt.subplot(nrows, ncols_sub, n + 1)
                ax.grid(which='major', color='#DDDDDD', linewidth=0.7)
                ax.grid(which='minor', color='#EEEEEE', linestyle=':', linewidth=0.4)
                ax.minorticks_on()
                ax.plot(t, chan_data, linestyle='-', linewidth=1, color="blue", label=chans)
                
                # 设置Y轴标签和范围
                ax.set_ylabel(Naming_Ylabels(chans))
                # 优先使用传入的对应通道的ylim,否则用数据的极值(留5%余量)
                if 'ylim_dict' in kwarg and chans in kwarg['ylim_dict']:
                    y_min, y_max = kwarg['ylim_dict'][chans]
                else:
                    y_min, y_max = chan_data.min() * 0.95, chan_data.max() * 1.05
                ax.set_ylim([y_min, y_max])
                
                # 设置X轴范围和标签
                ax.set_xlim([t[0], t[-1]])
                ax.set_xlabel('Time [s]')
                
                # 图例设置(统一字体大小)
                ax.legend(loc='best', prop={'size': 7}, ncol=2)
            
            plt.tight_layout(h_pad=0.5, top=0.95)
            save_name = f"{k}_{os.path.basename(outfile[:-4])}_{subTitle}.pdf"
            plt.savefig(save_name, bbox_inches='tight')
            plt.close()

# 使用示例(按需调整)
# Monitor_Channels = ['FREQ_1', 'VOLT_2', 'CURR_3']
# ylim_config = {'FREQ_1': (49.5, 50.5), 'VOLT_2': (0.9, 1.1)}
# plot_subplots(Monitor_Channels, 'TestPlot', ylim_dict=ylim_config)

额外说明

  • 如果需要针对特定参数类统一Y轴范围(比如所有频率子图用相同范围),可以在统计数据时按参数类型分组计算极值。
  • 全局字体设置可以根据需求调整plt.rcParams的参数,比如font.size、font.family等,确保所有文本元素风格统一。

内容的提问来源于stack exchange,提问作者Md Shamiur Rahman Shaummo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:17:56