Related
I have a matrix, A, that contains 50 rows and 4 columns, and the entries are filled with integers. My interest is to construct a stacked 3D bar plot from this data. However, using bar3(A,'stacked') creates a row of 50 bars, whereas I want the bars to be plotted at the coordinates of a grid of size 5 (vertical) x 10 (horizontal). So the first bar in the row would be at location (1,1), second bar at (1,2), 11th bar at (2,1) and so on until the 50th bar which would be at (5,10). I can't seem to find a way to do this in Matlab, is this possible at all?
Thank you in advance!
I agree with #cris, there are better ways to represent your data. However, something like this would work if you still want to do use a 3D bar plot:
figure
hold on
for i = 1:5
Ai = A(10*(i-1)+1:10*i,:);
h = bar3(1:10,Ai,'stacked');
for ih = 1 :length(h)
x = get(h(ih), 'Xdata');
set(h(ih), 'Xdata', x+i-1);
end
end
view(3)
I have a tricky question, which I think cannot be simply answered.
I have a large data table and want to save bar charts for each 2 corresponding mean values. I already did that with "for loop", but I cannot set different colors to my bars and cannot set proper spaces between bars and axes.
That's the simplest example:
k = [2 5]
bar(k)
Matlab thinks about those data [2 5] as about one "group" and it does not give a possibility of changing color for only one bar.
Of course, when we have different "groups", colors are changeable.
y = bar([1 2 3; 4 5 6]);
y(2).FaceColor = 'red';
But what about my example? I need only two bars, and I need to color them differently. Also, I want to set a small space between each bar and the axes (and again with two bars it is not that simple, and I cannot use "bar width" because that doesn't give me what I really want).
Does anyone know how to get around this?
Thanks for any reply!
Mary
A good trick could be add zero column for each group:
k = [2 5;0 0];
bar(k,'grouped')
UPDATE
Another solution to have different color could be using location in bar:
k = [2 5];
figure(1);
hold on;
h=bar(1,k(1));
set(h,'FaceColor','k');
h=bar(2,k(2));
set(h,'FaceColor','b');
hold off
As far as I know, this requires the use of a custom bar plot, since Matlab's barplots use dynamic colormaps. Personally, I like the GRAMM toolbox for all these customizations: [GRAMM on file-exchange] [GRAMM on github].
Here's an example:
x = [1 2];
y = [1 1.5];
c = x;
custom_map = ...
[1 0.3673 0.4132;
0 0.7375 0.8344];
clear g
g(1,1)=gramm('x',x,'y',y,'color',c);
g(1,1).geom_bar('width',0.2);
g(1,1).set_title('Width = 0.2');
g(1,2)=gramm('x',x,'y',y,'color',c);
g(1,2).geom_bar('width',0.8);
g(1,2).set_title('Width = 0.8');
g.set_names('y','','x','');
g.set_color_options('map',custom_map);
g.axe_property('YTick',[],'LineWidth',1,'YColor',[1 1 1],'XLim',[0.5 2.5],'XTick',[1 2])
figure('Position',[100 100 600 300]);
g.draw();
The histogram function is one option that will easily handle the spacing and x-axis labeling, but you'll have to plot each bar separately to independently control the colors:
k = [2 5];
histogram('Categories', {'ONE'}, 'BinCounts', k(1), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0 0.4470 0.7410]);
hold on;
histogram('Categories', {'TWO'}, 'BinCounts', k(2), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0.8500 0.3250 0.0980]);
Here is an option to workaround this. You can use diag(k) to create a 2*2 matrix with all zeros except the main diagonal that will be with your values, and Matlab will read it as 2 different groups. Then you change the Xdata of the 'dummy' bars (which you don't see but take some space on the x axis to nan so Matlab will ignore it.
k = [2 5];
b = bar(diag(k));
set(b,{'XData'},{[1 nan],[nan 1]}); % remove the group you don't want
set(gca,{'xticklabel','XTick'},{{'ONE','TWO'},[0.85 1.15]});
b(2).FaceColor = 'r'; % choose a different color
The result:
And if you want to generalize this to more groups (here it's 5):
k = 1:5;
data = diag(k);
xdata = eye(numel(k))./eye(numel(k)); % a martix of nan with 1 on the main diagonal
b = bar(diag(k));
% remove all data except one bin in all groups:
set(b,{'XData'},mat2cell(xdata,ones(size(data,1),1),size(data,2)))
X = xlim; 5 get x-axis limits
w = (1-X(1))/(numel(k)/2); % calculate the width of one bin
set(gca,'XTick',X(1)+w/2:w:X(2)) % set the X ticks to the center of the bins
set(gca,'xticklabel',{'ONE','TWO','THREE','FOUR','FIVE'}); % set the labels
set(b,{'FaceColor'},mat2cell(lines(numel(k)),ones(size(data,1),1),3)); % set the colors
and you get:
And finally, if you want them to 'hover' a little above the x-axis, you can add the following lines:
b(1).BaseLine.Color = 'none'; % remove the base line
ylim([-0.1 max(k(:))]) % shift the bars up a little
and get:
I have a set of values and a bunch of corresponding colours. The colours are dependent on the x labels but they are already in the correct order. How do I plot the bar chart such that the colours correspond to the correct bars. For example...
y= [2 4 12 7 15]'
bar_colour={'b';'b';'g';'r';'k'}
hp=bar(y,bar_colour{:})
At the moment, all the bars are in one colour.
In this case I think a loop is justified:
y = [2 4 12 7 15]'; %'
bar_colour = {'b';'b';'g';'r';'k'};
hold on
for n = 1:numel(y)
bar(n, y(n),bar_colour{n});
end
OK for example the numeric value of one of my data is large and the numeric value of one of my data is small.
A = [130000 310000 200000 400000]';
B = [16 32 5 10]';
I am doing the following.
figure;
bar(1:4,[A B],0.5,'stack');
Since the value of A is lot high than B, I want a secondary y-axis. Otherwise the values of B cannot be seen on the stacked bar chart.
You can use plotyy to plot two bar charts on different y-axes in the same figure.
x = [1,2,3];
y1 = [1000,2000,3000];
y2 = [0.5,0.3,0.1];
[AX,H1,H2] = plotyy(x, y1, x, y2, 'bar', 'bar');
set(H1, 'FaceColor', [1 0 0], 'BarWidth', 1)
This isn't a stacked bar chart like you had before (one set of data vertically on top of the other) but it doesn't make sense include data on different scales in a stacked bar chart.
My task is to write MATLAB code to produce a 4-part logo as shown in the screenshot. The top left should be black and the bottom right should be white. The other
two colours should be chosen randomly by the program.
I have taken the following approach:
clear all
clc
close all
x = [1 4 1 4 1 6.5 7 7];
y = [3 4 5.5 5 8 7 8 3];
fill(x,y,'k')
which creates the upper left black part. I wonder if that approach is good enough and if it is, what is the next step. I thought of storing those two variables in a shape object or something (I'm not familiar with Matlab) and rotate it somehow. Could you help me with that?
You don't need to rotate, just use the symmetry
clear all
clc
close all
x = [1 4 1 4 1 6.5 7 7];
y = [3 4 5.5 5 8 7 8 3]-3;
clrs=jet(10);
fill(x,y,'k')
hold on;
fill(2*max(x)-x,y,clrs(round(rand*10),:))
fill(x,-y,clrs(round(rand*10),:))
fill(2*max(x)-x,-y,'w')
The easiest way to do this all this, is to make sure that your center point (i.e. the point where the different colors meet), is positioned at [0,0]. Then a rotation of the figure (by multiple of 90°) boils down to changing the sign of either the x and/or y values of your contour.
If you need the figure to be at a point different from [0 0], just add these coordinates after you did the rotation.
So starting from your code, you can do this:
x = [1 4 1 4 1 6.5 7 7]-7;
y = [3 4 5.5 5 8 7 8 3]-3;
c = [5 6];
col = [0 0 0;
rand(2,3);
1 1 1];
fill( x+c(1), y+c(2),col(1,:)); hold on;
fill(-x+c(1), y+c(2),col(2,:));
fill( x+c(1),-y+c(2),col(3,:));
fill(-x+c(1),-y+c(2),col(4,:)); hold off;
edit: Clarification for the col and c variables.
The variable col contains the colors to be used in rgb style, where each row is a color. rand generates uniformly random numbers in the range [0,1], which is also where the values for the colors are expected to be. In the code above a 2x3 random matrix is generated, so that means 2 random colors which fits perfectly within the col matrix.
The variable c contains the center of your figure. If you look at the plot, the center will be at [5 6] (so 5 along the x axis and 6 along the y axis). You could use two variables instead, but I think that keeping both together in a variable is easier to deal with. I would personally do the same for your x and y variables, as that would allow you to use rotation matrices more easily, but that's just a matter of choice.