Use bar3 instead of bar to plot multiple data in Matlab - matlab

I have 3 matrices A, B and C where each of them is of size 21x2. I use bar to plot each one separately. I'm wondering how I can plot the three together using bar3?
So using this code:
A=rand(21,2);
B=rand(21,2);
C=rand(21,2);
fig=figure();b1=bar(A);
fig2=figure();b2=bar(B);
fig3=figure();b3=bar(C);
will generate these three figures:
A:
B:
C:
And what I want to do is that I want them to be all the the same figure but plotted behind each other in the z direction to be something like this

The idea is to create new variables that contain all the data you want in each row intercalated with NaNs. Just that change gives you almost the solution.
for ii=1:size(A,1)
A1((ii-1)*3+1)=A(ii,1);
A1((ii-1)*3+2)=A(ii,2);
A1((ii-1)*3+3)=NaN;
B1((ii-1)*3+1)=B(ii,1);
B1((ii-1)*3+2)=B(ii,2);
B1((ii-1)*3+3)=NaN;
C1((ii-1)*3+1)=C(ii,1);
C1((ii-1)*3+2)=C(ii,2);
C1((ii-1)*3+3)=NaN;
end
h=bar3(horzcat(A1',B1',C1'))
However, I am guessing that you also want to modify the colors.
To do this, the idea is that you can get the colour data for each bar row using get(h(nrow),'Cdata').
with this trick and your own colormap you should be able to colour the bars independently. It is not straightforward, but where's the fun if its easy!

Related

Creating a Bar Graph where each Bar is a Histogram

I'm creating a line plot, where the y value of each point is the average value of vector i. The x value of each point is i.
I want to visualise the distribution of numbers in each vector, preferably all on the same graph.
Is there a way I can make a bar graph, where each bar, i, is something like a colorbar, representing the histogram of vector i. So essentially I want to end up with 20 or so bars, each being a histogram.
Or if there is a better way to visualise numerous histograms on a single plot, I'd like to hear it.
I solved the problem using Dan's solution. I took a histogram of each vector (with specific bin intervals), and stored them all in a 2D matrix (Each column is a complete histogram). Then displayed it with image() (Don't have access to imshow).
I did have to mess around with the axis labels though, as the image() function was plotting it according to the coordinates of the 2D matrix, rather than the values in the original vectors. Fixed that up with some calls to set(gca,'YTickLabel/YTick'). Also had to set the YDir back to 'normal' rather than 'reverse'. I think image() was flipping it.

Change histogram to curve in Matlab but not "fit"

I am using matlab to process data to get a radius distribution function. Now I get data(an array) of different distances of other atoms to 1 specific atom.
I used the "hist" command (hist(radius1,400)) and get a histogram:
But what I want is a curve, like this:
http://upload.wikimedia.org/wikipedia/commons/3/31/Lennard-Jones_Radial_Distribution_Function.svg
I tried some fit command, but it would give me a normal-distribution-like curve, which is not what I want. actually no fit is fine, I only want a curve to show its varying.
The raw data was a 4000*1 array of radius, is there any other way to get a curve of the top of each bar of the histogram?
Thanks so much.
Instead of automatically plotting a histogram using hist, you can get it to output the values:
[x, c] = hist(radius1,400);
x is the data in each bin, c the centre of each bin, so this replicates a histogram and then overplots a line on it (which will just connect the top of each bar so it may not look as smooth as you hoped):
bar(c,x);
hold on
plot(c,x,'r');
It is possible to use fit with an anonymous function as a custom model, but that may be overkill in this situation.

Matlab bar plot grouped but in different y scales

I have two sets of data, and I want to plot using bar graph. But the problem is these two sets of data are at quite different scale. If I just use the bar(A), it would look like this: grouped but the second data set is barely visible because the scale.
However, if I use the plotyy(x,y1,x,y2), the plot will be like this: two sets of data are in different scale, but the bar graphs are not grouped, the second data sets overlaps to the first.
So I am wondering if there is a way to plot the bar graph grouped like the first figure, but the two datasets are using separate y scales? Or is there a way to adjust the horizontal offset of the bar graph in second plot so it looks like "grouped".
Thanks!
This uses the plotyy(x1,y1,x2,y2,fun1,fun2) variant of plotyy:
%// Set these three variables as desired
offset = (x(2)-x(1))/8;
width = (x(2)-x(1))/4;
colors = {'b','g'};
%// Do the plot
plotyy(x-offset,y1,x+offset,y2, #(x,y) bar(x,y,width,colors{1}), #(x,y) bar(x,y,width,colors{2}));
If you prefer x-ticks to appear only on used x values:
h = plotyy(x-offset,y1,x+offset,y2, #(x,y) bar(x,y,width,colors{1}), #(x,y) bar(x,y,width,colors{2}));
set(h,'xtick',x)

Matlab - Band-like diagram

I am trying to reproduce a band-like diagram, like the one in figure from windows defrag.
In principle, it can be easily obtained by doing a contourf of a matrix which is constant along one dimension (corresponding to the vertical dimension in the picture).
Do you know if there are native ways to obtain such a diagram?
Try:
vec = [1*ones(1,10), 2*ones(1,5), 3*ones(1,20), 4*ones(1,15)];
image('CData',vec, 'CDataMapping','direct')
colormap(lines(4))
axis tight off
or maybe even:
imshow(repmat(vec,10,1), lines(4))
imshow(vec, lines(4), 'YData',[0 10])
This is using an indexed image with direct color mapping, where the value 1 gets mapped to first color, value 2 mapped to second color and so on.. You can of course use your own colormap by specifying a N-by-3 matrix.
Not sure if this is what you are requesting, but there is no specialised function in matlab to do this. However, you could easily implement your own function that uses line to draw a large number of lines based on your data. Using get/set on the handles of the lines would let you control their colour, width etc. (also based on the input to your function).

Grouping bar3 plots like bar

I'm wondering if it is possible to get the same grouping behavior of bar plots into bar3.
For example, if you plot
bar(rand(3));
you get 3 bars for each point; bar groups the different y values for each x. Now I would like to do the same with a 3D data. That is that I have several slices of 2D data that I want to visualize as groups of bars. Then, if my data is
data = rand(3,3,2);
I would like to see data(1,1,:) as a group of bars, and data(1,2,:) as another group and so on.
Is it possible? I cannot find a way of achieving this.
Edit: I'm adding more details, to explain it better.
Lets said that we have two, or more, sets of data {x_(i,j)^s}. What I need is to group in the same grid position (i,j), all the sets s. In this question, they are grouping the data sets side by side, not element-wise, like this:
x1(s1) x1(s2) x1(s3) x2(s1) x2(s2) x2(s3) x3(s1) x3(s2) x3(s3)
x4(s1) x4(s2) x4(s3) x5(s1) x5(s2) x5(s3) x6(s1) x6(s2) x6(s3)
x7(s1) x7(s2) x7(s3) x8(s1) x8(s2) x8(s3) x9(s1) x9(s2) x9(s3)
I would like the bar command behavior, it tends to group when putting more than one data set. I would like to know if it is possible.
I am not sure I fully understood, but if you are looking for grouped behavior like you mention with bar(rand(3)) then you can try
figure; bar3(rand(5),'grouped');
% or maybe
figure; bar3(rand(5),'stacked');
or try to rearrange the data in data so it can work better with bar3 with reshape:
data = rand(3,3,2);
% now each data(i, j, :) will be in single row
changeddata = reshape(data , [size(data , 1)*size(data , 2) 2]);
figure; bar3(changeddata);
figure; bar3(changeddata ,'grouped');
figure; bar3(changeddata ,'stacked');
Maybe if you can give a code example for how it's supposed to look in one group, it would help to understand your question better.
If you want to group bars in 3D bar plots, but you are happy o small groups (let's say 2 or 3 bars each group) then you can simply take advantage of the Y argument in bar3:
BAR3(Y,Z,WIDTH)
so you specify the location of the two groups of bars with two shifted Y vectors.
example:
bar3(0:3:9,rand(4,4),0.3)
hold on
bar3(1:3:10,rand(4,4),0.3)
then you can edit the label the way it suits you.