Using 3 "y" axes for multiple plot
15 views (last 30 days)
Show older comments
Hello,
I am working with multiple plots in MATLAB and I would like to use three different "y" axis for the different axes within a single figure. I have no problem using two "y" axes with yyaxis, I can't include that function in my for loop (this loop reads the data from each column to be plotted from the Excel file). I read about a function called addaxis, but I don't know how to use it.
Also, I would like the plots to have different colors for each "y" axis, since MATLAB defaults to red for Y1 and blue for Y2. Any ideas on how to achieve this?
Any suggestions would be greatly appreciated!
Best Regards!
Lucas.
clc;
clear;
nombre_excel = 'Hoja_fuente.xlsx';
datos = readtable (nombre_excel);
encabezados = datos.Properties.VariableNames(2:end);
encabezados = strrep(encabezados, '_', ' ');
t = datetime(datos.Tiempo,'ConvertFrom', 'datenum', 'Format', 'HH:mm:ss'); %Si da probemas: sustituir 'datenum' por 'excel'
numero_columnas=size(datos,2) - 1;
fig = figure('Name','Representación interactiva MATLAB', 'NumberTitle','off', 'Color', 'w');
hold on;
grid on;
for i=2:numero_columnas+1
y_i = datos(:,i);
y_i = table2array(y_i);
if max(y_i) <= 100
yyaxis right
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, SeriesIndex = 1, marker='.', markersize = 1, color = 'r');
end
if max(y_i) > 100
yyaxis left
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, SeriesIndex = 1, marker='.', markersize = 1, color = 'b'); %['Y_' num2str(i-1)]
end
end
title('Gráfica Interactiva');
legend('show');
xlabel('Tiempo( hh:mm:ss )', 'FontSize', 12);
%ylabel(encabezados, 'Rotation', 0, 'Color', 'b');
ax=gca;
ax.XAxis.Exponent = 0;
ax.XAxis.TickLabelFormat = 'HH:mm:ss';
axis tight;
ax.XAxis.SecondaryLabelFormatMode = 'manual';
set(gca, 'Position', [0.056770833333333,0.157667386609071,0.894270833333333,0.809935205183586]);
legend('Location', 'southoutside', 'NumColumns', 6, 'Orientation', 'horizontal', 'NumColumnsMode','manual', 'Interpreter','none', 'FontSize', 8, 'FontWeight', 'bold', 'FontName', 'Arial Narrow', 'box', 'on');
set(legend, 'IconColumnWidth', 15, 'Position', [0.004678527128273,0.041036717062635,0.988802104021113,0.058815920456996]);
format long g;
This code is working but It can only plot 2 "y" axes; but if I try the addaxis in order to implement the third "y" axis, my code It´s not working:
clc;
clear;
nombre_excel = 'Hoja_fuente.xlsx';
datos = readtable (nombre_excel);
encabezados = datos.Properties.VariableNames(2:end);
encabezados = strrep(encabezados, '_', ' ');
t = datetime(datos.Tiempo,'ConvertFrom', 'datenum', 'Format', 'HH:mm:ss'); %Si da probemas: sustituir 'datenum' por 'excel'
numero_columnas=size(datos,2) - 1;
fig = figure('Name','Representación interactiva MATLAB DQA', 'NumberTitle','off', 'Color', 'w'); %Preguntar si NumberTitle on o off
hold on;
grid on;
for i=2:numero_columnas+1
y_i = datos(:,i);
y_i = table2array(y_i);
if max(y_i) <= 20
addaxis(t, y_i, [0 20],'LineWidth',1.3,'Color','b')
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, 'SeriesIndex', 1, 'Marker', '.', 'MarkerSize', 1, 'Color', 'green');
end
if 20 < max(y_i) && max(y_i) <= 100
addaxis(t, y_i, [0 100], 'LineWidth',1.3,'Color','r')
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, SeriesIndex = 1, marker='.', markersize = 1, color = 'red'); %['Y_' num2str(i-1)]
end
if max(y_i) > 100
addaxis(t, y_i, [0 max(y_i)],'LineWidth',1.3,'Color','g')
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, SeriesIndex = 1, marker='.', markersize = 1, color = 'b'); %['Y_' num2str(i-1)]
end
end
title('Gráfica Interactiva DiagnóstiQA');
legend('show');
xlabel('Tiempo( hh:mm:ss )', 'FontSize', 12);
%ylabel(encabezados, 'Rotation', 0, 'Color', 'b');
ax=gca;
ax.XAxis.Exponent = 0;
ax.XAxis.TickLabelFormat = 'HH:mm:ss'; %QUITAR ESTA LINEA DE CODIGO SI PREFERIMOS FORMATO TEMPORAL mm:ss
axis tight; %INSTRUCCIONES: tight, tickaligned o padded %en vez de axis puedo usar xlim o ylim si solo quiero ajustar 1 de los ejes
ax.XAxis.SecondaryLabelFormatMode = 'manual'; %ESTO SOLUCIONA EL 31 -1!
set(gca, 'Position', [0.056770833333333,0.157667386609071,0.894270833333333,0.809935205183586]); %El segundo numero es el margen desde el borde inferior de la ventana y el cuarto número es la altura de los ejes
legend('Location', 'southoutside', 'NumColumns', 6, 'Orientation', 'horizontal', 'NumColumnsMode','manual', 'Interpreter','none', 'FontSize', 8, 'FontWeight', 'bold', 'FontName', 'Arial Narrow', 'box', 'on');
set(legend, 'IconColumnWidth', 15, 'Position', [0.004678527128273,0.041036717062635,0.988802104021113,0.058815920456996]);
format long g;
2 Comments
dpb
on 28 Jan 2025
Edited: dpb
on 29 Jan 2025
...
for i=2:numero_columnas+1
y_i = datos(:,i);
y_i = table2array(y_i);
if max(y_i) <= 20
addaxis(t, y_i, [0 20],'LineWidth',1.3,'Color','b')
plot(t, y_i, 'LineWidth', 1.5, 'DisplayName', encabezados{i-1}, 'SeriesIndex', 1, 'Marker', '.', 'MarkerSize', 1, 'Color', 'green');
end
...
Every time you call addaxis it will create another one so you'll end up with as many as there are columns by using it inside a loop. To have only three total you would need to follow the idea I showed below of collecting all the columns of each of the three sizes via a logical addressing vector of columns and plot each of those in one call. The simple binary of isbig() and ~isbig() won't work here because of more than two states, but it would be simple enough to build the array for each group...
BKPTS=[20 100];
isSmall =all(ttD{:,:}<=BKPTS(1));
isMedium=all(ttD{:,:}>BKPTS(1) & ttD{:,:}<=BKPTS(2));
isLarge =all(ttD{:,:}>BKPTS(2));
where I reverted again to the use of the timetable because it will let you address only the numeric variables without the time...
dpb
on 28 Jan 2025
I had an earlier comment that seems to have gotten lost -- in it I suggested an easier alternative for specifically three y axes would be the FEX submission <plotyyy>. It isn't quite as flexible, but it is somewhat simpler interface as well. You will still need to pass the three sets as arrays, however, rather than looping to make it work as you wish.
Accepted Answer
dpb
on 28 Jan 2025
ombre_excel = 'Hoja_fuente.xlsx';
datos = readtable (nombre_excel);
datos.Properties.VariableNames=strrep(datos.Properties.VariableNames,'_',' '); % rename the variables in the table
datos.Tiempo=datetime(datos.Tiempo,'ConvertFrom', 'datenum', 'Format', 'HH:mm:ss'); % convert in the table itself
ttD=table2timetable(datos); % convert to timetable
numero_columnas=width(datos)-1; % width instead of size(x,2)
fig = figure('Name','Representación interactiva MATLAB', 'NumberTitle','off', 'Color', 'w');
hold on;
grid on;
BIG=100; % the logic size value as variable, not magic number in code so can change
isbig=any(max(ttD{:,:})>BIG); % logic vector of which are the big columns
yyaxis right
plot(ttD.Tiempo,ttD{:,isbig}),'.-r','LineWidth',1.5,'markersize',1); % plot the big uns...
yyaxis left
plot(ttD.Tiempo,ttD{:,~isbig}),'.-b','LineWidth',1.5,'markersize',1); % then the little guys...
title('Gráfica Interactiva');
xlabel('Tiempo( hh:mm:ss )', 'FontSize', 12);
ax=gca;
ax.XAxis.Exponent = 0;
ax.XAxis.TickLabelFormat = 'HH:mm:ss';
axis tight;
ax.XAxis.SecondaryLabelFormatMode = 'manual';
set(gca, 'Position', [0.056770833333333,0.157667386609071,0.894270833333333,0.809935205183586]);
displaynames=[ttD.Properties.VariableNames(isbig) ttd.Properties.VariableNames(~isbig)]; % put names in order plotted for legend
hLg=legend(displaynames,'Location', 'southoutside', 'NumColumns', 6, 'Orientation', 'horizontal', 'NumColumnsMode','manual', 'Interpreter','none', 'FontSize', 8, 'FontWeight', 'bold', 'FontName', 'Arial Narrow', 'box', 'on');
set(hLg, 'IconColumnWidth', 15, 'Position', [0.004678527128273,0.041036717062635,0.988802104021113,0.058815920456996]);
Would shorten the code by using MATLAB array indexing by logical condition on which columns match the given condition. The conversion to the timetable is convenient because then the X time variable isn't considered part of the table data so the logical addressing vector length matches automagically the number of numeric variables in the table. Likewise with the VariableNames property, instead of including the time, it has only the data in the timetable so it also matches and then can select for the legend by the order in which the plots were created using the same logical indexing in the same order.
More Answers (0)
See Also
Categories
Find more on Axis Labels in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!