Matlab Bar Plot with multiple X-Axis - matlab

i've been struggling with this for some time.
i want to be able to plot the following example except while using a bar plot.
simple plot that needs to be converted to bar plot
this was implemented by myself. This is basically two plot overlay each other with a different axes each (current example shows the same ticks values but i want them to be changes later on)
my problem is that using bar plot changes axis location like so and i cannot resolve it. see image below:
desired image but lower axis are not aligned
The axes here are not aligned. i need both to start at the same place, that is the most left bar
your help is much appreciated
my code below:
close all
figure
y= magic(10)
a=axes('Position',[.1 .2 .8 .7],'XColor','b');
% hold on;
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
xticklabels( {3:12});
legend;
hold on
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
b= axes('Position',[.1 .1 .8 1e-12],'XColor','r')
xticklabels( {4:13});
legend;
EDIT:
managed to solve it - see update code below
close all
figure
y= magic(10)
ax1=axes('Position',[.1 .2 .8 .7],'XColor','b');
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
ax = gca
xticklabels( {3:12});
legend;
hold on
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
axPos = ax1.Position;
ax2 = axes('Position', (axPos .* [1 1 1 1e-3])-[0 .07 0 -1e-3] , 'XColor', 'r', 'linewidth', 2);
set(ax2,'XLim',[-0.2 11.2])
set(ax2,'XTick',(1:10))
xticklabels( {4:13});

Just use same x-limit for two bar plots. The MATLAB function is 'xlim'.
figure
y= magic(10)
a=axes('Position',[.1 .2 .8 .7],'XColor','b'); hold all;
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
xticks(3:1:12); xlim([0 15])
legend;
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
b= axes('Position',[.1 .1 .8 1e-12],'XColor','r'); xlim([3 12]);
xticks(4:1:13); xlim([0 15])
legend;

Related

MATLAB last plot in subplot overlays other plots

Firstly, apologies in advance, as I'm new to MATLAB (and coding).
I'm trying to put multiple plots in a subplot (4,9,n) however the last plot overlays the rest of the plots and is the only one containing data.
I'd like each plot to look like something like this:
Line plot with two x axes
Here's a snippet of the code I'm using (because I'm new, I haven't used a loop, so I've got code for each separate figure!):
%% TMR2
%set up data
TMR2 = HEOBI1{HEOBI1.STNNBR==2,:}
x1 = TMR2(:,[4])
x2 = TMR2(:,[5])
x3 = TMR2(:,[7])/25
y = TMR2(:,[3])
%set up figure in subplot
subplot(4,9,1)
%set up secondary (H2O2) axis
b=axes('Position',[.1 .1 .8 1e-12]);
set(b,'Units','normalized');
set(b,'Color','none');
b.XColor=[0 153/255 0];
%primary plot (DFE and FEII)
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
plot(x1,y,'-o','Color',[221/255 15/255 4/255],...
'MarkerFaceColor',[221/255 15/255 4/255])
set(gca,'Ydir','reverse')
xlim([0 3])
hold on
plot(x2,y,'-o','Color',[0 153/255 153/255],...
'MarkerFaceColor',[0 153/255 153/255])
plot(x3,y,'-o','Color',[0 153/255 0],...
'MarkerFaceColor',[0 153/255 0])
hold off
title('2')
%Set secondary (H2O2) axis limit
set(b,'xlim',[0 25]*3);
Finishing with:
%% TMR40
%set up data
TMR40 = HEOBI1{HEOBI1.STNNBR==40,:}
x1 = TMR40(:,[4])
x2 = TMR40(:,[5])
x3 = TMR40(:,[7])/25
y = TMR40(:,[3])
%set up figure in subplot
subplot(4,9,36)
%set up secondary (H2O2) axis
b=axes('Position',[.1 .1 .8 1e-12]);
set(b,'Units','normalized');
set(b,'Color','none');
b.XColor=[0 153/255 0];
%primary plot (DFE and FEII)
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
plot(x1,y,'-o','Color',[221/255 15/255 4/255],...
'MarkerFaceColor',[221/255 15/255 4/255])
set(gca,'Ydir','reverse')
xlim([0 3])
hold on
plot(x2,y,'-o','Color',[0 153/255 153/255],...
'MarkerFaceColor',[0 153/255 153/255])
plot(x3,y,'-o','Color',[0 153/255 0],...
'MarkerFaceColor',[0 153/255 0])
hold off
title('40')
%Set secondary (H2O2) axis limit
set(b,'xlim',[0 25]*3);
And here's what my final output looks like:
Incorrect Subplot
#Suever I thought about your suggestion a bit more and took out all code for axes for each of the subplots. I then set up the subplot with handles and gave each subplot a handle. My code now starts like this:
%% Subplot setup
figure;
for k = 1:36
h(k) = subplot(4,9,k);
end
and the code for each subplot now looks like this:
%% TMR40
%set up data
TMR40 = HEOBI1{HEOBI1.STNNBR==40,:}
x1 = TMR40(:,[4])
x2 = TMR40(:,[5])
x3 = TMR40(:,[7])/25
y = TMR40(:,[3])
%set up plot
subplot(h(36))
%primary plot (DFE and FEII)
plot(x1,y,'-o','Color',[221/255 15/255 4/255],...
'MarkerFaceColor',[221/255 15/255 4/255])
set(gca,'Ydir','reverse')
xlim([0 3])
hold on
plot(x2,y,'-o','Color',[0 153/255 153/255],...
'MarkerFaceColor',[0 153/255 153/255])
plot(x3,y,'-o','Color',[0 153/255 0],...
'MarkerFaceColor',[0 153/255 0])
hold off
title('40')
The subplots are now displaying correctly and I can edit individual subplots with their respective handles. Thanks again for your help!
It's seems like you're confused about what subplot does and your terminology is a bit off. You don't "setup a figure in a subplot". A figure is the entire window that holds all of your plots, and subplot is an axes that holds your various plot objects (lines, images, surfaces, etc.).
The main issue though is that subplot creates an axes. This means that you don't need to call axes() after calling subplot otherwise that call to axes will create a new axes that does not obey the layout of the subplot inputs.
So instead of
subplot(9,4,36)
a = axes('Position', [.1 .2 .8 .7]);
plot(x, y)
Just do
subplot(9,4,36)
plot(x,y)

MATLAB Subplot Make Figure Larger

I am plotting two maps next to each other using subplot. However, now, the image is turning out like this:
Is there any way to make the map part of the image larger? I would like to plot the maps side by side, by in this image, the resolution is low and the size is small.
%% Graph one site at a time
nFrames = 6240; % Number of frames.
for k = 94:nFrames
h11 = subplot(1,2,1); % PM2.5
% Map of conterminous US
ax = figure(1);
set(ax, 'visible', 'off', 'units','normalized','outerposition',[0 0 1 1]);
ax = usamap('conus');
set(ax,'Position',get(h11,'Position'));
delete(h11);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax,str2double(Lat_PM25{k})', str2double(Lon_PM25{k})', 25, str2double(data_PM25{k})', 'filled');
% Colorbar
caxis([5 30]);
h = colorbar;
ylabel(h,'ug/m3');
% Title
title(['PM2.5 24-hr Concentration ', datestr(cell2mat(date_PM25(k)), 'mmm dd yyyy')]);
%%%%
h22 = subplot(1,2,2); % O3
% Map of conterminous US
ax2 = usamap('conus');
set(ax2,'Position',get(h22,'Position'));
delete(h22);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax2, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax2,str2double(Lat_O3{k})', str2double(Lon_O3{k})', 25, str2double(data_O3{k})'*1000, 'filled');
hold on
% Colorbar
caxis([10 90]);
h = colorbar;
ylabel(h,'ppb');
% Title
title(['O3 MDA8 Concentration ', datestr(cell2mat(date_O3(k)), 'mmm dd yyyy')]); % Title changes every daytitle(str);
% Capture the frame
mov(k) = getframe(gcf); % Makes figure window pop up
% Save as jpg
eval(['print -djpeg map_US_' datestr(cell2mat(date_PM25(k)),'yyyy_mm_dd') '_PM25_24hr_O3_MDA8.jpg']);
clf
end
close(gcf)
To change the amount of space the data occupies in the figure, you can use this command:
set(gca,'Position',[0.1 .1 0.75 0.85])
You'll have to play with the numbers a bit, to get things look nice. Note that Matlab rescales everything when you resize the figure window, so the optimal numbers depend on the window size you want to use.
On the other hand, you want to make the map bigger in comparison to the colorbar. You cannot make it without changing your window size, because your maps are already as high as the color bars. I would suggest to:
Set caxis to the same range in both plots.
Remove the colorbar on the left one.
Increase the height of your figure window to make the maps occupy as much width as possible.
Put the two images nicelye side by side using the command above.
For more information, see Matlab Documentation on Axes Properties.
Example:
% Default dimenstions
figure
x = 1:.1:4;
y = x;
[X, Y] = meshgrid(x,y);
subplot(1,2,1)
h = pcolor(X, Y, sin(X).*cos(Y)*2);
set(h, 'EdgeAlpha', 0);
axis square
colorbar
subplot(1,2,2)
h = pcolor(X, Y, sin(Y).*cos(X));
set(h, 'EdgeAlpha', 0);
axis square
colorbar
% adjust dimensions
subplot(1,2,1)
set(gca, 'Position', [0.1 0.1 0.3 0.85])
subplot(1,2,2)
set(gca, 'Position', [0.55 0.1 0.3 0.85])
This blog post has many great examples of FileExchange scripts dealing with size of subplots.
subplot_tight works very well and makes the subplots larger. Instead of writing in subplot(1,2,1), use subplot_tight(1,2,1)
My problem was similar -> scaling subplots in a figure a bit more up. Important for me though, was to maintain the aspect ratio that I've set before.
Enhancing the answer from #texnic in order to not have to set the values manually, one might use the following:
scale = 1.1; % Subplot scale
subplot(1,2,1)
% Your plotting here ...
pos = get(gca, 'Position'); % Get positions of the subplot [left bottom width height]
set(gca, 'Position', [pos(1) pos(2) pos(3)*scale pos(4)*scale]); % Scale width and height
Understanding this, one can also easily implement a parametric move of the subplot.

Zoom region within a plot in Matlab

I'm using Matlab to produce figures, and I'm wondering if there is a way to plot a zoomed region in a figure of the overall data?
I have scatter data plotted over one week, with the x-axis in hours, and I want to zoom into the first 3 hours, and display them within the main figure with the x-axis label of minutes.
The plotting code I have so far is as follows:
allvalsx = marabint(:,2)
allvalsy = marabint(:,5)
subvalsx = marabint(1:7,2);
subvalsy = marabint(1:7,2);
%% Plots the scatter chart.
sizemarker = 135
handle = scatter(allvalsx, allvalsy, sizemarker, '.')
figure(1)
axes('Position',[.2 .2 .2 .2])
handle2 = scatter(subvalsx, subvalsy, '.r')
title(plotTitle)
xlabel('Time since treatment (hours)')
ylabel('Contact angle (deg)')
% Axis scales x1, x2, y1, y2
axis([0, marabint(length(marabint),2) + 10, 0, 120]);
% This adds a red horizontal line indicating the untreated angle of the
% sample.
untreatedLine = line('XData', [0 marabint(length(marabint),2) + 10], 'YData', [untreatedAngle untreatedAngle], 'LineStyle', '-', ...
'LineWidth', 1, 'Color','r');
% Adding a legend to the graph
legendInfo = horzcat('Untreated angle of ', untreatedString)
hleg1 = legend(untreatedLine, legendInfo);
% This encases the plot in a box
a = gca;
% set box property to off and remove background color
set(a,'box','off','color','none')
% create new, empty axes with box but without ticks
b = axes('Position',get(a,'Position'),'box','on','xtick',[],'ytick',[]);
% set original axes as active
axes(a)
% link axes in case of zooming
linkaxes([a b])
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [8.267 5.25]);
set(gcf,'PaperPosition',[0 0.2625 8.267 4.75]);
set(gcf,'PaperPositionMode','Manual');
set(handle,'Marker','.');
print(gcf, '-dpdf', '-r150', horzcat('markertest4.pdf'));
This produces the following
Can anyone help me out with this?
yeah, I think I know what you need. Try this:
zoomStart = 0;
zoomStop = 3;
set(gca, 'XLim', [zoomStart zoomStop])
Let me know if that doesn't do what you need, and I'll give you a different way.

Multiple y plots on same logarithmic scale for the x-axis

I am trying to plot 3 curves using the semilogx matlab function and add a fourth line to an additional y axis on the right. All of them should be plotted on the same logarithmic scale for the x-axis. The following code indicates the derived error; the x-axis is incorrect. The figure has to have a single x-axis mode of ticks, the logarithm one. How could this be fixed?
Plus, how can I add a legend for these 4 curves?
close all, clc
figure, semilogx([1:100:1000],[rand(1,10)],'bo-'),
xlabel('xlabel'),ylabel('ylabel'), hold on;
semilogx([1:100:1000], [rand(1,10)], 'ro-'), hold on,
semilogx([1:100:1000], [rand(1,10)], 'ko-'), hold off
legend('1','2','3','Location','Best')
ax1 = gca;
ax2 = axes('YAxisLocation','right',...
'Color' , 'none',...
'YColor', 'm');
linkaxes([ax1 ax2 ], 'x')
x4 = [1:100:1000];
y4 = [rand(1,10)*2];
line(x4, y4, 'color', 'm', 'Marker','x','LineStyle',':', 'parent',ax1)
ylabel('y2')
You can use plotyy function to plot two of your lines, one on the right and one on the left. You can then hold on and plot the remaining lines using semilogx.
plotyy([1:100:1000], [rand(1,10)], [1:100:1000], [rand(1,10)]*2, #semilogx);
hold on;
semilogx([1:100:1000], [rand(1,10)], 'ro-');
semilogx([1:100:1000], [rand(1,10)], 'mo-');
hold off;
legend('Line1','Line2','Line3','Line4','Location','Northwest')

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings