grouped bar chart with 2 y-axes is displayed as stacked bar - matlab

I would like to plot the grouped bar chart for the comparison of three methods. I tried the following code and it is displayed as stacked bar chart.can you please help
dice =[0, 3, 5];
no_of_region=[42, 12, 5];
figure;
bar(dice',.2,'grouped','FaceColor',[0 .5 .5],'EdgeColor',[0 .9 .9],'LineWidth',1.5)
ylabel('Dice Similarity index')
yyaxis right
bar(no_of_region, .2,'grouped','EdgeColor', 'r', 'LineWidth', 2);
legend('Dice Similarity Index','Number of regions')
legend('Location','northwest')
XTickLabel={'a' ; 'b';'c'};
XTick=[1 2 3]
set(gca, 'XTick',XTick);
set(gca, 'XTickLabel', XTickLabel);
set(gca, 'XTickLabelRotation', 45);
xlabel('Different Methods', 'Fontsize', 16)
ylabel('Number of Regions', 'Fontsize', 16)
title('Comparison of Algorithms', 'fontsize', 20);
set(gcf,'color','w');
OUTPUT I GOT AS:

One easy solution is to shift the bars left and right by half of their width (or more if you would like space between them). Here is the new code, which is also cleaned a bit stylistically:
% parameters
dice = [0, 3, 5];
no_of_region = [42, 12, 5];
X = [1, 2, 3]; % common x values for plot
bar_width = 0.2; % width of bars
% initialize figure
figure;
% left plot
bar(X.' - bar_width/2, dice', bar_width, 'grouped', ...
'FaceColor', [0 .5 .5], ...
'EdgeColor', [0 .9 .9], ...
'LineWidth', 1.5);
ylabel('Dice Similarity index');
% right plot
yyaxis right;
bar(X.' + bar_width/2, no_of_region, bar_width, 'grouped', ...
'EdgeColor', 'r', ...
'LineWidth', 2);
% plot formatting
legend({'Dice Similarity Index', 'Number of regions'}, ...
'Location', 'northwest');
XTickLabel = {'a' ; 'b'; 'c'};
XTick = X;
set(gca, ...
'XTick', XTick, ...
'XTickLabel', XTickLabel, ...
'XTickLabelRotation', 45);
xlabel('Different Methods', 'FontSize', 16);
ylabel('Number of Regions', 'FontSize', 16);
title('Comparison of Algorithms', 'FontSize', 20);
set(gcf, 'color', 'w');
Depending on desired behavior, you also might consider replacing figure; by clf;, which clears the existing figure or opens a new figure window if there is not already one open.

Related

Plotting bar and reverse bar into the Y axis

I am trying to plot two sequences of bars, using the same y-axis. One of the sequences goes on the bottom, the other goes on top (from top to bottom), and the y axis is split into two (half for the bottom bars and half for the top bars). The bottom bars use one color, like green, and the top bars use another color, red, and the y axis uses the respective colors on each half on the axis.
Example:
Question: How can I split the y-axis in the way represented in the figure above?
Thanks for helping! =D
You could create this effect by layering three axes and adjusting their properties accordingly. For example:
% The larger left axes:
hLeft = axes('Position', [0.1 0.1 0.8 0.8], ... % Normalized position
'XLim', [0 11], 'YLim', [0 3], ... % Set desired limits
'Box', 'off'); % Turn off outline
hLeft.XLabel.String = 'Time'; % Add an x label
hLeft.YLabel.String = 'Line'; % Add a y label
hLeft.Title.String = 'Bar-bar-plot'; % Add a title
hLine = line(hLeft, 1:10, rand(1,10)+1, 'Color', 'k'); % Plot a sample line
% The lower right axes:
hLower = axes('Position', [0.1 0.1 0.8 0.4], ... % Position over bottom half
'XLim', [0 11], 'YLim', [0 1.5], ... % Set desired limits
'YColor', [0 0.5 0], 'Color', 'none', ... % Change colors
'YAxisLocation', 'right'); % Position y axis
hLower.XAxis.Visible = 'off'; % Turn of x axis
hLower.YLabel.String = 'Bar 1'; % Add a y label
hold on;
hBarLower = bar(hLower, 1:10, rand(1,10), ... % A sample bar plot
'FaceColor', 'none', 'EdgeColor', [0 0.5 0]);
% The upper right axes:
hUpper = axes('Position', [0.1 0.5 0.8 0.4], ... % Position over top half
'XLim', [0 11], 'YLim', [0 1.5], ... % Set desired limits
'YColor', [1 0 0], 'Color', 'none', ... % Change colors
'YAxisLocation', 'right', ... % Position y axis
'YDir', 'reverse'); % Reverse y axis
hUpper.XAxis.Visible = 'off'; % Turn off x axis
hUpper.YLabel.String = 'Bar 2'; % Add a y label
hold on;
hBarUpper = bar(hUpper, 1:10, rand(1,10), ... % A sample bar plot
'FaceColor', 'none', 'EdgeColor', [1 0 0]);
% Add a legend:
hLegend = legend(hUpper, [hLine hBarLower hBarUpper], ...
{'line', 'bar 1', 'bar 2'}, 'Color', 'w');
And here's the plot:
You can reposition the legend as needed by left clicking on it and dragging it to the best spot.

imagesc with multiple axis and ticklines

I have a [12 x 6] matrix A that I represent with imagesc and on which I impose some thick tick-lines:
figure
imagesc(A)
set(gca,'xtick', linspace(0.5,size(A,2)+0.5,C+1),...
'ytick', linspace(0.5,size(A,1)+0.5,B*al+1),'linewidth',3);
set(gca,'xgrid', 'on', 'ygrid', 'on', 'gridlinestyle', '-', 'xcolor',
'k', 'ycolor', 'k');
set(gca, 'XTickLabelMode', 'manual', 'XTickLabel', [],'YTickLabel', []);
colorbar
I then want to impose some thinner tick-lines to split in two each box delimited by the thicker lines:
ax1 = gca;
ax1_pos = get(ax1,'Position'); % position of first axes
ax2 = axes('Position',ax1_pos,...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none');
set(gca,'xtick', linspace(0.5,size(A,2)+0.5,2*C+1),'linewidth',1);
The result is clearly not satisfying. How could I fix it? I thought that 'Color','none' would have done the trick...
Instead of trying to modify tick lengths and adding a second axes, I would just plot some extra lines on top of your image. This should achieve what you want:
% Some sample data:
A = rand(12, 6);
% Plot image:
imagesc(A);
set(gca, 'Visible', 'off');
hold on;
colorbar;
% Plot horizontal lines:
yLines = repmat((0:size(A, 1))+0.5, 2, 1);
xLines = repmat([0.5; size(A, 2)+0.5], 1, size(yLines, 2));
line(xLines, yLines, 'LineWidth', 3, 'Color', 'k');
% Plot thick vertical lines:
xLines = repmat((0:2:size(A, 2))+0.5, 2, 1);
yLines = repmat([0.5; size(A, 1)+0.5], 1, size(xLines, 2));
line(xLines, yLines, 'LineWidth', 3, 'Color', 'k');
% Plot thin vertical lines:
xLines = repmat((1:2:size(A, 2))+0.5, 2, 1);
yLines = repmat([0.5; size(A, 1)+0.5], 1, size(xLines, 2));
line(xLines, yLines, 'LineWidth', 1, 'Color', 'k');
And here's the plot:

Multiple y axes in MATLAB (axis alignment issue when printing)

Here is a sample of a strange problem. I'd like to plot curves with multiple y axes and I use a fairly common method in MATLAB.
function plot_test()
clear;
savefile = 1;
scrsz = get(0,'ScreenSize');
figure('Position',[1 1 0.9 * scrsz(3) 0.9 * scrsz(4)]);
hold on;
box on;
x = 0:1:10;
h1 = plot(x, x.^2 , 'r', 'LineWidth', 2.5);
%Axis label
xlabel('XLabel', 'FontSize', 20, 'Interpreter', 'latex');
ylabel('YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(gca, 'FontSize', 20, 'LineWidth', 3);
ax1 = gca;
ax2 = axes('Position',get(ax1,'Position'),'XAxisLocation','top','YAxisLocation','right','Color','none','XColor','none','YColor','k');
linkaxes([ax1 ax2],'x');
hold on
box on;
h2 = plot(x, x, 'b', 'Parent', ax2, 'LineWidth', 2.5);
ylabel('Second YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(gca, 'FontSize', 20, 'LineWidth', 3);
hl=legend([h1 h2],{'First Line','Second Line'});
set(hl,'FontSize',15,'Location','Northwest', 'Orientation','Vertical')
%Save pdf
if savefile
% Backup previous settings
prePaperType = get(gcf,'PaperType');
prePaperUnits = get(gcf,'PaperUnits');
preUnits = get(gcf,'Units');
prePaperPosition = get(gcf,'PaperPosition');
prePaperSize = get(gcf,'PaperSize');
% Make changing paper type possible
set(gcf,'PaperType','<custom>');
% Set units to all be the same
set(gcf,'PaperUnits','inches');
set(gcf,'Units','inches');
% Save the pdf
print -dpdf Test.pdf;
% Restore the previous settings
set(gcf,'PaperType',prePaperType);
set(gcf,'PaperUnits',prePaperUnits);
set(gcf,'Units',preUnits);
set(gcf,'PaperPosition',prePaperPosition);
set(gcf,'PaperSize',prePaperSize);
end
The objective is to print a PDF of the figure and save it in the same folder as Test.pdf. This is accomplished but the axes are misaligned. On my Windows machine it looks horrible while on a Mac it looks almost okay (but if you look closely, the y-axes are indeed misaligned at the bottom).
This only happens when I use a second axis. Without that, all this runs perfectly. Any idea why?
Okay, so I found a way: The trick is to use plotyy. Sample code below
function plot_test2()
clear;
savefile = 1;
scrsz = get(0,'ScreenSize');
figure('Position',[1 1 0.9 * scrsz(3) 0.9 * scrsz(4)]);
hold on;
box on;
x=(0:1:10);
y1=x;
y2=x.^2;
[hAx, hLine1, hLine2] = plotyy(x,y1,x,y2);
%Axis label
xlabel(hAx(1),'XLabel', 'FontSize', 20, 'Interpreter', 'latex', 'Color', 'k');
ylabel(hAx(1),'YLabel', 'FontSize', 20, 'Interpreter', 'latex', 'Color', 'k');
ylabel(hAx(2),'Second YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(hAx,{'ycolor'},{'k';'k'})
set(hAx,{'FontSize'},{20;20}, {'LineWidth'}, {3;3})
set(hLine1,'LineWidth', 3)
set(hLine2,'LineWidth', 3)
set(hLine1,'Color', 'r')
set(hLine2,'Color', 'b')
hl=legend([hLine1 hLine2],{'First Line','Second Line'});
set(hl,'FontSize',15,'Location','Northwest', 'Orientation','Vertical')
%Save pdf
if savefile
% Backup previous settings
prePaperType = get(gcf,'PaperType');
prePaperUnits = get(gcf,'PaperUnits');
preUnits = get(gcf,'Units');
prePaperPosition = get(gcf,'PaperPosition');
prePaperSize = get(gcf,'PaperSize');
% Make changing paper type possible
set(gcf,'PaperType','<custom>');
% Set units to all be the same
set(gcf,'PaperUnits','inches');
set(gcf,'Units','inches');
% Save the pdf
print -dpdf Test.pdf;
% Restore the previous settings
set(gcf,'PaperType',prePaperType);
set(gcf,'PaperUnits',prePaperUnits);
set(gcf,'Units',preUnits);
set(gcf,'PaperPosition',prePaperPosition);
set(gcf,'PaperSize',prePaperSize);
end

Plot second y axis using plot and fill (without plotyy)

Here is my code
clear all;clc
x = linspace(0, 10, 100);
axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YColor', [0 0 0]);
fill(x, circshift(sin(x), 50), 'red', 'EdgeColor','None');
ylabel('Fancy Sine', 'FontSize', 11);
% Adding this the upper vanishes and the y axes is on left not right side
axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YAxisLocation', 'Right', ...
'Color', 'none');
plot(x, x, 'Color', [.2 .4 .8]);
ylabel('Line Graph', 'FontSize', 11);
xlabel('X', 'FontSize', 11);
The single axis works fine
But when I want to add the second axis, the first disappears and the new axis is not on the right, but left side..
But both plots should be in one axis and the second y axis should be on the right side.
How to achieve this?
plot automatically sets the axis properties to the default. Use hold to stop this or specify the axis properties after your plot call.
An example of the former:
clear all;clc
x = linspace(0, 10, 100);
ax1 = axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YColor', [0 0 0]);
p1 = fill(x, circshift(sin(x), 50), 'red', 'EdgeColor','None','Parent',ax1);
ylabel('Fancy Sine', 'FontSize', 11);
% Adding this the upper vanishes and the y axes is on left not right side
ax2 = axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YAxisLocation', 'Right', ...
'Color', 'none');
hold on
p2 = plot(ax2,x, x, 'Color', [.2 .4 .8]);
hold off
ylabel('Line Graph', 'FontSize', 11);
xlabel('X', 'FontSize', 11);
Edit1: The reason you don't need to do this for your fill call is because it creates a patch object in your axes and does not invoke a plot command.

How to get arrows on axes in MATLAB plot?

I want to plot something like this:
x = 0:0.01:10;
f = #(x) 50* 1.6.^(-x-5);
g = #(x) 50* 1.6.^(+x-10);
plot(x, f(x));
hold on
plot(x, g(x));
I can't manage to get axes similar to the ones in this figure:
I know I can remove the top and right lines like in this question, but I don't know how to get the arrows on the edges.
I don't need the additional annotations, but I would like to remove the ticks on the axes. I know how to do this when the axes are "normal", but I'm not sure if it must be done in another way when the axes are already manipulated.
Does anyone know how to do this?
Well, don't say I didn't warn you :)
% Some bogus functions
f = #(x) 50* 1.6.^(-x-5);
g = #(x) 50* 1.6.^(+x-10);
% Point where they meet
xE = 2.5;
yE = f(xE);
% Plot the bogus functions
figure(1), clf, hold on
x = 0:0.2:5;
plot(x,f(x),'r', x,g(x),'b', 'linewidth', 2)
% get rid of standard axes decorations
set(gca, 'Xtick', [], 'Ytick', [], 'box', 'off')
% Fix the axes sizes
axis([0 5 0 5])
% the equilibrium point
plot(xE, yE, 'k.', 'markersize', 20)
% the dashed lines
line([xE 0; xE xE], [0 yE; yE yE], 'linestyle', '--', 'color', 'k')
% the arrows
xO = 0.2;
yO = 0.1;
patch(...
[5-xO -yO; 5-xO +yO; 5.0 0.0], ...
[yO 5-xO; -yO 5-xO; 0 5], 'k', 'clipping', 'off')
% the squishy wiggly line pointing to the "equilibrium" text
h = #(x)0.5*(x+0.2) + 0.1*sin((x+0.2)*14);
x = 2.7:0.01:3.5;
plot(x, h(x), 'k', 'linewidth', 2)
% the static texts
text(xE-yO, -0.2, 'Q^*', 'fontweight', 'bold')
text(-2*yO, yE, 'P^*', 'fontweight', 'bold')
text(-2*yO, 4, 'Price', 'rotation', 90, 'fontsize', 14)
text( 4, -0.2, 'Quantity', 'fontsize', 14)
text( .5, 4.2, 'Demand', 'fontsize', 14, 'rotation', -55)
text( 4.0, 3.3, 'Supply', 'fontsize', 14, 'rotation', +55)
text( 3.6, 2.1, 'Equilibrium', 'fontsize', 14)
Result:
The symbolic math toolbox has provisions for making these arrows, but without that toolbox you are stuck with drawing the arrows yourself. The following code should be useful for this purpose:
% determine position of the axes
axp = get(gca,'Position');
% determine startpoint and endpoint for the arrows
xs=axp(1);
xe=axp(1)+axp(3)+0.04;
ys=axp(2);
ye=axp(2)+axp(4)+0.05;
% make the arrows
annotation('arrow', [xs xe],[ys ys]);
annotation('arrow', [xs xs],[ys ye]);
% remove old box and axes
box off
set(gca,'YTick',[])
set(gca,'XTick',[])
set(gca,'YColor',get(gca,'Color'))
set(gca,'XColor',get(gca,'Color'))
The only drawback is that for some figure window sizes you will have a 1-pixel white border below the arrows, and setting the LineWidth property of the axes to a ridiculous small value does not help.
But for printing, the small white border should not be relevant.