plotting bar chart make negative bars different colour to positive bars - matlab

I am plotting a bar chart in Matlab. I would like to know if it is possible to base the colours of the bars based on a simple condition? I would like all the positive bars to be say blue and the negative ones to be red. If this is possible can you please tell me how I can going about doing this in MATLAB?

Yes, it's possible, see this solution on MATLAB Central.
Here's some example code extracted from this. The third column of the data is used to determine which colour to apply to each bar. In your case, you just need to check whether each value is positive or negative and change the colour accordingly.
data = [.142 3 1;.156 5 1;.191 2 0;.251 4 0];
%First column is the sorted value
%Second column is the index for the YTickLabel
%Third column is the reaction direction
% Data(1,3) = 1 -> bar in red
% Data(1,3) = 0 -> bar in blue
% For each bar, check direction and change bar colour
H = data(:, 1);
N = numel(H);
for i=1:N
h = bar(i, H(i));
if i == 1, hold on, end
if data(i, 3) == 1
col = 'r';
else
col = 'b';
end
set(h, 'FaceColor', col)
end

Alternatively, you could include your conditions (here data>0 and data<0) as follows:
data = rand(8,1) - .5;
figure(1);
clf;
hold on;
bar(data.*(data>0), 'b');
bar(data.*(data<0), 'r');

Related

Matlab: Color individual groups, not individual bars within a group

This is my code:
Positions=[1:5];
Gap_Duration=[4,4,4,4,4,4;
2,2,2,2,2,2;
3,3,3,3,3,3;
4,4,4,4,4,4;
0,0,0,0,0,24];
H = barh(Positions,Gap_Duration,'stacked')
set(H([1 3 5]),'Visible','off')
ax = gca;
ax.YTick = [Positions];
ax.YTickLabel = {'AllOut','Port1In','Port2In','DeliverReward','Total Time Duration'};
xlabel('Time')
title('Lever Press Frequency')
I want to make the bars on the horizontal y-axes 1 color each (so all 'Deliver Reward bars are red, all 'Port2In' bars are blue, etc.) Any clue how to do this?
To workaround the issue, generate separate horizontal bar graphs for each row while keeping the width of rest of the elements equals to NaN so nothing extra gets plotted. i.e.
Lp = length(Positions);
colors = hsv(Lp); %Generating group colors (or define custom colors if needed)
hold on;
for k=1:Lp
GapD = NaN(size(Gap_Duration)); %Initializing a dummy Gap_Duration matrix
GapD(k,:) = Gap_Duration(k,:); %Filling with the content of the current row
H = barh(Positions, GapD, 'stacked');
set(H, 'FaceColor', colors(k,:)); %Making the color same for all current bars
set(H([1 3 5]),'Visible','off'); %This condition is from your code
end

Matlab bars: changing the color of the bar and the space between bars and axes

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:

Rectangular grid using MATLAB

I have two cell arrays and each cell has a matrix x = (10X5). Each row in x is an array (between -1 and 1) with a mean "m" and std "s". Now i want to represent this matrix in a rectangular grid using MATLAB such that each box has a mean (orange color) and std deviation (filled with red colour in either side of mean) as shown in the example. So basically there should be 10X2 rectangular grids (corresponding to 10 rows and two cells). Can someone please help me with this? I looked up online but could not find anything.
You can use boxplot to create the initial structure of the plot, and then alter them to represent what you want. Each matrix x is converted to one grid plot, and the plots are placed side by side with subplot.
Here is a short code to do what you want:
A = {rand(10,5)*2-1,rand(10,5)*2-1}; % your cell array
for n = 1:numel(A)
subplot(1,2,n)
x = A{n};
means = mean(x,2);
stds = std(x,[],2);
% create boxplot for all variables:
bx = boxplot(x.','Orientation','horizontal');
% remove what's unnecessary:
delete(bx([1:4 7],:))
% set the median to mean:
set(bx(6,:),{'XData'},...
mat2cell([means means],ones(size(x,1),1),2))
set(bx(6,:),{'Color','LineWidth'},{[1 0.7 0],3})
% set the interQ range to std:
std_bounds = repmat(means,1,5)+bsxfun(#times,stds,[-1 1 1 -1 -1]);
set(bx(5,:),{'XData'},mat2cell(std_bounds,ones(size(x,1),1),5))
set(bx(5,:),'Color',[0.8 0 0])
for k = 1:size(std_bounds,1)
patch(std_bounds(k,:),get(bx(5,k),'YData'),[0.8 0 0],...
'FaceAlpha',0.7,...
'EdgeColor','none')
end
xlim([-1 1])
ax = gca;
ax.Children = ax.Children([end 1:end-1]);
% create the grid:
set(ax,{'YGrid','GridColor','GridAlpha','XTick','XAxisLocation','YTick'},...
{'on','k',1,[-1 0 1],'top',(1:size(x,1))+0.5})
% set the zero line:
line(ax,zeros(size(x,1)+2,1),(0:size(x,1)+1).','LineStyle','--','Color','k')
if n>1
set(ax,'YTickLabel',[])
end
end
It creates this:

MATLAB : bar graph_ modify parameters on axis

I have a bar graph with 2 different data (each with a different color as you can see on the picture). I would like to move the x-axis so it crosses at y=-100 (for example). So if a data = -40, I would like to have a bar from -100 to -40.
An other question : is it possible to write each value of the x-axis vertically (because with all the values, we can't see anything).
The last question : is it possible to have 2 different scales for the x_axis ?
Thank you in advance,
Best regards,
Here is some code to get you going. Everything is commented so that should be easy to follow:
clear
clc
close all
%// Generate dummy data
y = -90*rand(1,20);
NumY = numel(y);
HalfData = round(NumY/2);
%// Loop to color half in pink and half in blue
hold all
for k = 1:NumY
hBar = bar(k,y(k));
if k <= HalfData
set(hBar,'FaceColor',[1 0 1])
else
set(hBar,'FaceColor',[0 0 1])
end
end
hold off
%// Get xtick labels and position for future use
xtLabels = cellstr(get(gca,'XTickLabel')).';
xtPos = get(gca,'XTick');
%// Change baseline value
set(hBar,'BaseValue',-40)
%// Get baseline to change its properties if you want
hBaseL = get(hBar,'Baseline');
set(hBaseL,'LineStyle','--','Color','k','LineWidth',3)
%// Adjust axis limits. Remove labels to place them vertically
set(gca,'XLim',[0 NumY],'XTickLabel',{''})
%// Get correct position for xlabel text
YLimPoArrays = min(get(gca,'YLim'));
YLimPoArrays = repmat(YLimPoArrays,numel(xtPos),1);
%// Place text positioned vertically with a small y offset
text(xtPos,YLimPoArrays-3,xtLabels,'HorizontalAlignment','center','Rotation',90,'FontSize',15)
And the output:
Hope that helps!

How can I change the color of bars in bar graph?

I'd like to create a bar graph where I change the color of some bars.
The code for my bar graph is the following:
y = [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, ...
-0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
bar(y)
I want the first six bars to be black and the last 6 bars to be blue, but I have no idea how to do it.
You need to plot them separately (but on the same axes):
bar(1:6,y(1:6),'k')
hold on
bar(7:numel(y),y(7:end),'b')
set(gca,'xtick',1:numel(y))
As the answer from HERE suggests, since the version MATLAB R2017b, you can do so through the CData property. You can find more at THIS documentation page.
Simply put, using the following approach will get you what you need.
b = bar(rand(10,1));
b.FaceColor = 'flat';
% Change the color of the second bar. Value assigned defines RGB color value.
b.CData(2,:) = [.5 0 .5];
The following is adapted from Bar plot with bars in different colors on MATLAB Central:
y= [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, -0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
for ii=1:12
h = bar(ii-0.5, y(ii));
if ii == 1
hold on
end
if ii<=6
col = 'k';
else
col = 'b';
end
set(h, 'FaceColor', col,'BarWidth',0.4)
end
axis([0 12 -0.2 1])
hold off
No need to plot separately, here is the simple solution:
y= [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, -0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
figure,
bar(y)
y1 = zeros(1,length(y));
y1(3:5) = y(3:5);
hold on
h = bar(y1)
set(h, 'FaceColor', 'k')
See output
Very late as usual, but there is an easy way to 'trick' matlab.
You first define your colormap (for instance 3 different colors):
mycolors = lines(3) % or just specify each row by hand
Then you plot your bars in the following way:
bar(x,diag(y),'stacked'); % x will be usually defined as x = 1:number_of_bars
colormap(mycolors);
That's all. The magic comes from the diag function together with the 'stacked' tag that makes matlab think you have more data (but they are all 0).