I am plotting two arrays in one plot. The bar plot must show two y-axis as well as the bars next to each other. The problem occurs when I want to implement both requirements.
I can either plot the bars together with for example
Y = [5,2; 8,7; 9,8; 5,5; 4,3];
figure
bar(Y)
Or I can create two y-axis (which I do currently with my data):
y = [lr_flights2018, lr_income2018];
yyaxis left
b = bar(1:length(y),lr_flights2018);
ylabel('Life Rating/flights ratio')
yyaxis right
p = bar(1:length(y),lr_income2018);
ylabel('Life Rating/income ratio')
set(gca, 'XTick', 1:length(y))
set(gca,'XTickLabel',{countries{:,1}})
xtickangle(90)
title('Correlations with life rating');
In the latter yyaxis separates the plots which results in the two plots stacked together. I want the plots to stand side by side for each bin as can be seen in
this example.
You can do this by manipulating the x position and the bar width
I manipulated your Y data as shown below, and made some new labels for the countries which you didn't provide in your example
figure;
Y = [5,2; 8,7; 9,8; 5,5; 4,3];;
lr_flights2018 = Y(:,1);
lr_income2018 = Y(:,2);
y = [lr_flights2018, lr_income2018];
yyaxis left
b = bar((1:length(y))+0.125,lr_flights2018, 'barwidth', 0.25);
ylabel('Life Rating/flights ratio')
yyaxis right
p = bar((1:length(y))-0.125,lr_income2018, 'barwidth', 0.25);
ylabel('Life Rating/income ratio')
set(gca, 'XTick', 1:length(y))
str = strread ( sprintf ( '%i\n', [1:5] ), '%s', 'delimiter', '\n' )
set(gca,'XTickLabel',str)
xtickangle(90)
title('Correlations with life rating');
Related
I'd like to have the legend (of some contours) over the colorbar of a surf plot.
How can I have a layout similar to the image in a figure plot?
From the black
colorbar;
legend('label1','label2','Location','northeastoutside');
to the red one?
You can manually change the position of both the colorbar and the legend
% Make a demo plot
figure(); hold on
plot( rand(20,3) ); % lines for the legend
peaks(10); % surface for the colorbar
view(3); % 3D view
% Create a legend and colorbar, retain their handles
L = legend( 'show', 'location', 'eastoutside' );
C = colorbar();
% Get some key variables from the current position of the colorbar/legend
% -> avg mid point of colorbar and legend
x = ( L.Position(1) + (C.Position(1)+C.Position(3)) ) / 2;
% -> Max width of the two objects
w = max( L.Position(3), C.Position(3) );
% -> A nominal y value and padding to dictate the spacing
y = 0.1;
pad = 0.05;
% Move the legend and colorbar
% First move the x/y coords of the legend to be on top, centred around common x
L.Position(1:2) = [x - L.Position(3)/2, 1 - y - L.Position(4)];
% Then move the x/y coords of the colorbar to be on the bottom, centred around common x
C.Position(1:2) = [x - C.Position(3)/2, y];
% Then resize the colorbar to use the vertical space not utilised by the legend
C.Position(4) = L.Position(2) - pad - y;
% By moving the legend/colorbar the axes will have "popped" to use the full width
% Need to move it to span between the current left edge and the newly moved leg/colorbar
ax = gca();
ax.Units = 'Norm';
ax.Position(3) = (x-w/2) - pad - ax.Position(1) ;
Result:
You can do this interactively by clicking the "Cursor" icon in the top of the plot window and adjusting the legend/colorbar. Once you have finished editing choose "Generate Code" in the "File" menu of the plot window to have code generated so you can repeatedly create the plot.
I have this script to obtain subplot with bar, but I would rather that the bars were side by side and with two y axes. How can I do? I have in this case the bars one above the other.
The result is shown in figure below.
% Create figure
figure1 = figure('NumberTitle','off','Name','Figure','Color',[1 1 1]);
%bar plot e scatter 2011
subplot1=subplot(3,2,1,'Parent',figure1)
x1 = (1:5)';
y1 = tweetsvsnewsS3.somma_1_2;
y2 = tweetsvsnewsS3.tweets_1;
yyaxis left
p1 = bar(x1,y1, 'BarWidth', 0.25);
p1(1).FaceColor = [0.56 0.10 0.74];
yyaxis right
p12=bar(x1,y2,'BarWidth', 0.25)
p12(1).FaceColor = [0.41 0.28 0.79];
box(subplot1,'on');
hold(subplot1,'off');
set(subplot1,'XGrid','on','XMinorGrid','on','XMinorTick','on','YGrid','on',...
'YMinorGrid','on','YMinorTick','on');
set(gca,'xtick',1:12,...
'xticklabel',{'Nov 24','Nov 25','Nov 26','Nov 27','Nov 28'})
ylabel('count');
title('Data','FontSize',12)
I tried also this script but I didn't have the second y axis. In figure there is the result.
% Create figure
figure1 = figure('NumberTitle','off','Name','Figure','Color',[1 1 1]);
%bar plot e scatter 2011
subplot1=subplot(3,2,1,'Parent',figure1)
x1 = (1:5)';
y1 = tweetsvsnewsS3.somma_1_2;
y2 = tweetsvsnewsS3.tweets_1;
p1 = bar(x1,[y1,y2],'BarWidth', 0.80);
p1(1).FaceColor = [0.56 0.10 0.74];
p1(2).FaceColor = [0.41 0.28 0.79];
box(subplot1,'on');
hold(subplot1,'off');
set(subplot1,'XGrid','on','XMinorGrid','on','XMinorTick','on','YGrid','on',...
'YMinorGrid','on','YMinorTick','on');
set(gca,'xtick',1:12,...
'xticklabel',{'Nov 24','Nov 25','Nov 26','Nov 27','Nov 28'})
ylabel('count');
title('Data','FontSize',12)
Your first script is the right one. You can have the bar plotted side by side if you set empty data in each dataset so that we can see the data behind. Note that you must also set the facecolor at the right position in your dataset.
[...]
yyaxis left
p1 = bar(x1,[y1 zeros(size(y1))]);
p1(1).FaceColor = [0.56 0.10 0.74];
yyaxis right
p12=bar(x1,[zeros(size(y2)) y2]);
p12(2).FaceColor = [0.41 0.28 0.79];
[...]
I have a simple, grouped bar plot. I'm trying to plot the error bars, too, but I can't seem to figure it out.
I'm not too great with for loops, but I don't know if that's the only solution to this, or if I can just add another line of code to plot the error bars.
Here's my code and graph:
% Plot raw data
y = [316.45 292.14 319.96; 305.59 287.99 295.21] % first 3 #s are pre-test, second 3 #s are post-test
err = [13.12 5.67 12.36; 12.43 6.83 11.67]
box on
bar(y)
set(gca,'xticklabel',{'Pre-test'; 'Post-test'})
ylim([200 360])
ylabel('RT (ms)')
xlabel('Session')
Here is a solution using the standard errorbar and bar functions. bar plots each group at the same x position, and uses the Xoffset property to shift the bars in a group. You can use the x position and Xoffset to plot the errorbars.
% Data
y = [316.45 292.14 319.96; 305.59 287.99 295.21] % first 3 #s are pre-test, second 3 #s are post-test
err = [13.12 5.67 12.36; 12.43 6.83 11.67]
% Plot
figure(1); clf;
hb = bar(y); % get the bar handles
hold on;
for k = 1:size(y,2)
% get x positions per group
xpos = hb(k).XData + hb(k).XOffset;
% draw errorbar
errorbar(xpos, y(:,k), err(:,k), 'LineStyle', 'none', ...
'Color', 'k', 'LineWidth', 1);
end
% Set Axis properties
set(gca,'xticklabel',{'Pre-test'; 'Post-test'});
ylim([200 360])
ylabel('RT (ms)')
xlabel('Session')
I have a problem with using bar and colormap.
I have a csv file like this which contains completion time for six tasks:
34,22,103,22,171,26
24,20,41,28,78,28
37,19,60,23,141,24
...
and I create a bar chart with of the means, and add the std variation errorbar.
res = csvread('sorting_results.csv');
figure();
y = mean(res)';
e = std(res);
hold on;
bar(y);
errorbar(y,e,'.r');
title('Sorting completion time');
ylabel('Completion time (seconds)');
xlabel('Task No.');
hold off;
colormap(summer(size(y,2)));
Why is the output like this? Why do the bars have the same color? And how do I put legends to the six bars?
A piece of code that does the magic. It doesn't use the canonical technique mentioned by #am304, as you will have a hard time setting up the legend with it. Here, for each one of the 6 input values, we plot a full 6 bars: one bar with the value and the remaining five set to zero.
x = rand(1,6); %create data
x_diag = diag(x); %zero matrix with diagonal filled with x
cmap = summer(6); %define colors to use (summer colomap)
figure('color','w','Render','Zbuffer'); %create figure
%bar plot for each x value
for ind_data = 1:length(x)
h_bar = bar( x_diag(ind_data, :)); %bar plot
set( get(h_bar,'children'), 'FaceVertexCData', cmap(ind_data,:) ) ; %color
hold on;
end
colormap('summer');
%legend-type info
hleg = legend( ('a':'f')' );
set(hleg, 'box', 'off');
%xticks info
set(gca, 'XTickLabel', ('a':'f')' );
%plot errors
e = ones(1,6) * 0.05;
errorbar(x, e,'.r');
set(gca, 'FontSize', 14, 'YLim', [ 0 (max(x) + max(e) + 0.1) ]);
See Coloring 2-D Bars According to Height in the MATLAB documentation. Only the first colour of the colormap is used to colour the faces, you need a bit of hack (as per code on that doc page) to do what you want.
That's how I draw two graphics (thanks for guys who helped me to do that):
clear
logsFolder = 'C:\logs\';
stocks = {'log'};
for stock = stocks
filename = [logsFolder stock{1} '.log'];
fLog = fopen(filename);
data = textscan(fLog, '%f:%f:%f:%f %f %f %f');
fclose(fLog);
% hh:min:sec:millisec
secvec = [60*60 60 1 1e-3];
x = [data{1:4}] * secvec';
y = data{5};
yPrice = data{6};
xindays = x / (24*60*60);
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
set(AX(1),'xtick',[]);
lo1 = min(y);
hi1 = max(y);
lo2 = min(yPrice);
hi2 = max(yPrice);
if (hi2/lo2 > hi1/lo1)
ylim(AX(1),[lo1 hi2/lo2 * lo1]);
ylim(AX(2),[lo2 hi2]);
else
ylim(AX(1),[lo1 hi1]);
ylim(AX(2),[lo2 hi1/lo1 * lo2]);
end
ticklabelformat(AX(2),'y','%g')
ticklabelformat(AX(2),'x',{#tick2datestr,'x','HH:MM:SS'})
title(stock);
% iNeedToDrawThat = data{7}
end
Input file example is available here As you can see my file contains the last column which I also want to display. The range should be from 0 (at the bottom of figure) to the maximum value (at the up of the graph). So I need to draw three graphics somehow. It's ok to omit axis with labels for the third graph as I already have two axis and I have no place to add third one. However it's ok to "overlap" two axis if possible.
I have no idea how to do that so I'm looking for your help.
I've tried that but it doesn't work:
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
I have already mentioned a similar question in the comments, it should give you plenty of ideas...
Anyway, I've put together a solution to plot multiple y axes. Right now the code is a bit involved, but it should be possible to refactor a re-usable function out of it (like the addaxis function on the File Exchange).
The idea is to first plot each curve in a separate axis (all superimposed), and make them transparent (except the bottom one). Next we create copies of this set of axes and shift them along the x-direction. We also make those copies transparent, but now we can show the tick-marks along the y-axis of each. Finally we give them correct z-order, and link the x and y limits so that we can use the pan and zoom functionality.
%# read and parse data from file
fid = fopen('log.log','rt');
C = textscan(fid, '%s %f %f %f', 'CollectOutput',true);
fclose(fid);
dt = datenum(C{1}, 'HH:MM:SS:FFF');
data = C{2};
NUM = size(data,2);
%# create a wider figure
hFig = figure('Position',get(0,'DefaultFigurePosition').*[1 1 1.7 1]);
%# some properties
clr = lines(NUM);
bgClr = get(0,'DefaultFigureColor');
pos = get(0,'DefaultAxesPosition');
pp = 0.1; % shift in normalized units: pos(1)
%# create plot axes (make axis invisible)
hAx = zeros(NUM,1);
for i=1:NUM
hAx(i) = axes('Parent',hFig, 'Color','none', ...
'XColor',bgClr, 'YColor',bgClr, ...
'Units','normalized', 'Position',pos+[(NUM-1)*pp 0 -(NUM-1)*pp 0]);
line(dt, data(:,i), 'Color',clr(i,:), 'Parent',hAx(i))
end
axis(hAx, 'tight') %# tight x/y limits
%# create shifted copies of axes to show y-ticks
hAxx = zeros(size(hAx));
for i=1:NUM
hAxx(i) = copyobj(hAx(i), hFig);
delete(get(hAxx(i),'Children')); %# keep only axis
set(hAxx(i), 'YColor',clr(i,:), ...
'Units','normalized', 'Position',pos+[(NUM-i)*pp 0 -(NUM-i)*pp 0]);
ylabel(hAxx(i), sprintf('Axis %d',i))
end
xlabel(hAxx(1), 'datetime')
title(hAxx(1), 'Log')
datetick(hAxx(1), 'x', 'HH:MM', 'keeplimits')
%# set 1st axis copy as current axis
set(hFig, 'CurrentAxes',hAxx(1))
%# adjust ticks of axes
set(hAx(1), 'Color','w') %# give white bg to 1st axis
set(hAxx(1), 'XColor','k') %# show xticks of 1st axis copy
set(hAxx(2:end), 'XTick',[], 'XTickLabel',[])
set(hAx, 'XTick',[], 'XTickLabel',[], 'YTick',[], 'YTickLabel',[])
%# fix z-order
for i=3:-1:1, uistack(hAxx(i),'top'), end
uistack(hAx(1), 'bottom')
%# link x/y limits so that panning/zooming works
lh = cell(NUM+1,1);
for i=1:NUM
lh{i} = linkprop([hAxx(i);hAx(i)], 'YLim');
end
lh{end} = linkprop([hAxx;hAx], 'XLim');
The result:
The panning/zooming is a bit funny, you have to initiate them by starting to drag from the side (the shifted colored axes). This is because the first one (corresponding to the blue line) is the one on top, thus catches all mouse clicks.
Note: I see you are using a custom function ticklabelformat, which I haven't tested in combination with the above code. I will leave that part to you..
HTH
sample use of hold on
figure;
plot(x1,y1);
hold on
plot(x2,y2);
plot(x3,y3);
hold off
do "figure" and "hold on" only once outside the loop. then plot all the graphs you need
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
if you do it the way you suggested using hold on, i.e. use plotyy() first then the axes won't adjust so if you 3rd series is out of the range of your first set of axes then it won't appear. Try just flipping them and see if that produces a result?
volume = data{7};
plot(xindays, volume);
hold on;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
This way the axes should adjust
For example:
t = 1:10;
x = t*2;
y = t*-2;
z = x + 1000;
Now compare
plot(t,z, 'r')
hold on
plotyy(t,x, t,y)
to
plotyy(t,x, t,y)
hold on
plot(t,z, 'r')