当前位置:首页>python>Matlab与Python绘制三y轴曲线图

Matlab与Python绘制三y轴曲线图

  • 2026-08-25 23:04:01
Matlab与Python绘制三y轴曲线图
案例代码见文末,感谢您关注PFC小姐姐,麻烦您多多对推文点赞、收藏及转发,并衷心希望您多多指教🙏,帮助PFC小姐姐进步提升。

科研需求

科研绘图里最常见的是双 y 轴,但有些场景会遇到三类量纲完全不同、又必须放在同一张图里对齐时间/位移/循环次数等同一横轴:比如位移-应力-能量、温度-电压-电流、轨道误差-残差RMS-权重因子……这时“三 y 轴”就派上用场了。

这篇推送给你两套可直接复用的做法:Matlab 和 Python(matplotlib),并把容易踩坑的点也一起讲清楚。

三 y 轴的核心不是“能不能画”,而是“怎么让读者一眼看懂”:

  • 三条曲线的颜色要和各自 y 轴刻度颜色一致

  • 第三个 y 轴不要挤在右边:把它“外移”一点(offset)

  • 减少视觉干扰:网格尽量轻、线宽一致、图例统一放一个位置

  • 避免误导:三 y 轴很容易被质疑“拉伸尺度”,建议在文中说明每个 y 轴的物理量与单位

Matlab解决方案

关键点:multiplotyyy子函数的妙用

主函数

clc

clear all

close all

data1=readmatrix("data1.csv");

data2=readmatrix("data2.csv");

data3=readmatrix("data3.csv");

ylabels{1}='Stress1 (MPa)';

ylabels{2}='Flow rate (mL/min)';

ylabels{3}='Stress2 (MPa)';

num_data=9000;

[ax,hlines] = multiplotyyy({data2(3:num_data,1),data1(3:num_data,2)},{data2(3:num_data,1),data1(3:num_data,3)},...

    {data2(3:num_data,1),data2(3:num_data,7)},ylabels);

lg=legend(cat(1,hlines{:}),'\sigma_1','Flow rate','\sigma_2');

set(lg, 'Units','normalized', 'Position',[0.14 0.71 0.2 0.2]);

set(lg, 'Box', 'off'); 

img =gcf;  

exportgraphics(img,'three_y.png','Resolution',600) %分辨率高,存图速度慢

请在微信客户端打开

子函数-multiplotyyy

function [ax,hlines] = multiplotyyy(set1,set2,set3,ylabels)

% MULTIPLOTYYY - Extends plotyy to include a third y-axis and allows the

% user to plot multiple lines on each set of axes.

%

% Syntax:  [ax,hlines] = plotyyy(set1,set2,set3,ylabels)

%

% Inputs: set1 is a cell array with the xdata and ydata for the first axes

%         set2 is a cell array with the xdata and ydata for the second axes

%         set3 is a cell array with the xdata and ydata for the third axes

%         ylabels is a 3x1 cell array containing the ylabel strings

%

% Outputs: ax -     3x1 double array containing the axes' handles

%          hlines - 3x1 cell array containing the lines' handles

narginchk(3,4)

if nargin==3

% Use empty strings for the ylabels

   ylabels{1}=' '; ylabels{2}=' '; ylabels{3}=' ';

end

validateattributes(set1,{'cell'},{})

validateattributes(set2,{'cell'},{})

validateattributes(set3,{'cell'},{})

fig = figure('units','normalized');

% Plot the first set of lines

ax(1) = axes('Parent',fig);

hlines{1} = plot(set1{:},'Color','b', 'LineWidth', 1.5);

% ylim([0 12]);

xlabels='Times (s)';

ax(1).YColor = 'b';

lines = set(hlines{1}(1),'LineStyle');

lines(end) = [];

nlines = numel(lines);

  set(gca,'Fontname','Times new roman');

% 右侧yy轴不显示刻度

yyaxis right

set(gca,'YTick',[]);          % 去掉右侧刻度

yyaxis left% 切回左侧

markers = set(hlines{1}(1),'Marker');

markers(end) = [];

nmarkers = numel(markers);

% % if numel(hlines{1}) > 1

% %     for idx = 1:numel(hlines{1})

% %         hlines{1}(idx).LineStyle = lines{rem(idx,nlines)+1};

% %         if numel(hlines{1}) > 4

% %             hlines{1}(idx).Marker = markers{rem(idx,nmarkers)+1};

% %         end

% %     end

% % end

% Plot the second set of lines

ax(2) = axes('Parent',fig);

hlines{2} = plot(set2{:},'Color',[0 0.5 0], 'LineWidth', 1.5);

 ylim([-5 20]);

set(ax(2),'YAxisLocation','right','Color','none','YColor',[0 0.5 0],...

'xlim',get(ax(1),'xlim'),'xtick',[],'box','off','XColor','k');

  set(gca,'Fontname','Times new roman');

if numel(hlines{2}) >= 1

for idx = 1:numel(hlines{2})

        set(hlines{2}(idx),'LineStyle',lines{rem(idx,nlines)+1})

if numel(hlines{2}) > 1

            set(hlines{2}(idx),'Marker',markers{rem(idx,nmarkers)+1});

end

end

end

%Set the axes position and size

pos = [0.1  0.15  0.7  0.8];

offset = pos(3)/5.5;

pos(3) = pos(3) - offset/2;

ax(1).Position = pos;

xlabel(ax(1), 'Times (s)');

ax(2).Position = pos;

% Determine the position of the third axes

pos3 = [pos(1) pos(2) pos(3)+offset pos(4)];

% Determine the proper x-limits for the third axes

limx1 = ax(1).XLim;

limx3 = [limx1(1)   limx1(1) + 1.2*(limx1(2)-limx1(1))];

ax(3) = axes('Parent',fig);

hlines{3} = plot(set3{:},'Color','r', 'LineWidth', 1.5);

 ylim([0 30]);

set(ax(3),'Position',pos3,'box','off',...

'Color','none','XColor','k','YColor','r',...

'xtick',[],'xlim',limx3,'yaxislocation','right',...

'XColor','none');

  set(gca,'Fontname','Times new roman');

% if numel(hlines{3}) > 1

%     for idx = 1:numel(hlines{3})

%         set(hlines{3}(idx),'LineStyle',lines{rem(idx,nlines)+1})

%         if numel(hlines{3}) > 4

%             set(hlines{3}(idx),'Marker',markers{rem(idx,nmarkers)+1});

%         end

%     end

% end

% Label all three y-axes

ax(1).YLabel.String = ylabels{1};

ax(2).YLabel.String = ylabels{2};

ax(3).YLabel.String = ylabels{3};

Python解决方案

关键点:就是没有关键点,很简单的,比matlab方便多了。

import csv

import matplotlib.pyplot as plt

from matplotlib import rc

# Set font to Times New Roman

rc('font', family='Times New Roman')

# Read stress_strain.csv

csv_reader1 = csv.reader(open("./stress_strain.csv"))

x0 = []

y0 = []

for line in list(csv_reader1)[1:]:

    x0.append(float(line[0]))

    y0.append(float(line[1]))

# Read zhenling.csv

csv_reader2 = csv.reader(open("./zhenling.csv"))

x1 = []

y1 = []

for line in list(csv_reader2)[1:]:

    x1.append(float(line[0]))

    y1.append(float(line[1]))

# Read crack_num.csv

csv_reader3 = csv.reader(open("./crack_num.csv"))

x2 = []

y2 = []

for line in list(csv_reader3)[1:]:

    x2.append(float(line[0]))

    y2.append(float(line[1]))

# Set the figure size

plt.figure(figsize=(12, 6))  # Increase the width to accommodate all axes

# Plotting

ax1 = plt.gca()

# Plot the stress-strain curve

lns1 = ax1.plot(x0, y0, 'k', label="stress-strain")

ax1.set_xlabel('strain')

ax1.set_ylabel('stress/pa')

ax1.set_ylim([0, 1.7e6])

# Create the second y-axis

ax2 = ax1.twinx()

# Plot the number of events curve

lns2 = ax2.plot(x1, y1, 'skyblue', label="number of Events")

ax2.set_ylabel('events of AE')

ax2.set_ylim([0, 10])

# Create the third y-axis

ax3 = ax1.twinx()

ax3.spines['right'].set_position(('outward', 40))  # Move the spine to the right to make space for the third axis

ax3.spines['right'].set_color('r')  # Set the color of the right spine to red

lns3 = ax3.plot(x2, y2, 'r', label="number of Cracks")

ax3.set_ylabel('crack_num', color='r')  # Set the label color to red

ax3.tick_params(axis='y', labelcolor='r')  # Set tick labels color for the third y-axis to red

ax3.set_ylim([0, 1200])

# Combine legends

lns = lns1 + lns2 + lns3

labs = [l.get_label() for l in lns]

ax1.legend(lns, labs, loc=2)

# Set the x-axis range

ax2.set_xlim([0, 0.015])

# Save and show the plot

plt.tight_layout()  # Adjust the layout to prevent overlapping

plt.savefig("stress_crack_zhenling-strain.png", dpi=150, pad_inches=0.1)

plt.show()

特别声明:

以上代码与文案均为网上资料整合而成,仅供广大同行们参考学习,如有侵权请联系删除。

如有其他需要,欢迎关注我的咸鱼号:pfc小姐姐

最新文章

随机文章