MATLAB Answers

How do I define colors for individual bars on my bar graph according to their values in MATLAB?

653 views (last 30 days)
I am trying to change colors on the individual bars in a bar graph according to the value of my data. When I issue the following command,
mydata=rand(1,5);
h=bar(mydata);
all the bars in my bar graph have the color blue. I want the bar colors to be such that if the value of 'mydata' is between [0, 0.2), the bars are black, if the value of my data is between [0.2, 0.6), the bars are blue, and if the value of my data is between [0.6, 1] then the corresponding bars are red.

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 7 Oct 2019
Edited: MathWorks Support Team on 7 Oct 2019
This issue has been resolved in MATLAB R2017b with the addition of a property "CData" to the "bar" function. To find out more about "CData", look at the following documentation page.
Prior to MATLAB R2017b, there was no built in function in MATLAB to control the color of individual bars in the bar graphs, but you can plot each bar individually and set the colors one at a time. For example:
mydata=rand(1,5);
figure(1)
hold on
for i = 1:length(mydata)
h=bar(i,mydata(i));
if mydata(i) < 0.2
set(h,'FaceColor','k');
elseif mydata(i) < 0.6
set(h,'FaceColor','b');
else
set(h,'FaceColor','r');
end
end
hold off
will produce a figure similar to the one below:
In MATLAB R2014a and earlier, the following example provides an alternative method to set the color of a bar in the chart based on its value.
First, obtain the handle to the 'Children' of a bar graph.
mydata=rand(1,5);
bar_h=bar(mydata);
bar_child=get(bar_h,'Children');
1. In order to map the color on the bars to your data, execute the following code:
set(bar_child,'CData',mydata);
Once 'CData' is set to "mydata", the colors on the individual bars are decided by comparing their values linearly with the default colormap "jet". You can change the colors on your barplot now by changing the colormap to one of the supplied colormaps. For example,
colormap(pink)
2. Since the default colormap is "jet", the minimum value in "mydata" is mapped to blue and the maximum value in "mydata" is mapped to red. To have more control on the colors on the bar, create your own colormap
mycolor=[0 0 0;0 0 1;1 0 0];
colormap(mycolor)
This will create a colormap with black as the first color, blue as the second, and red as the third color. Applying this colormap forces the color of the bars in the chart to be dependent on a linear scale between "mydata" and the number of available colors in the colormap. So the first third of the data range is black, the second third is blue, and the final third is red.
3. To apply specific colors for specific data ranges, set the 'CDataMapping' property to 'direct'.
set(bar_child,'CDataMapping','direct');
For example, to map all values between [0, 0.2) to black, all values between [0.2, 0.6) to blue, and all values between [0.6, 1] to red, execute the following code:
mycolor=[0 0 0;0 0 1;1 0 0];
for iCount=1:length(mydata)
if (mydata(iCount)<.2)
index(iCount)=1;
elseif(mydata(iCount)>=.6)
index(iCount)=3;
else
index(iCount)=2;
end
end
Set the 'CData' to the desired indices of the colormap.
set(bar_child, 'CData',index);
colormap(mycolor);
As an alternative to looping through the data, apply a vectorized method using logical arrays. In the following example, a logical array is found for a specific data range, and then wieghted by the color index associtated with the data range. The sum of the weighted logical arrays will result in the index vector.
blackRange = 1*(mydata<0.2);
redRange = 3*(mydata>=0.6);
blueRange = 2*~(blackRange+redRange);
index = blackRange + redRange + blueRange;
4. Note that if you have more than 150 datapoints to plot, you may see an error similar to the following after setting the 'CData' property: ERROR: Warning: Patch FaceVertexCData length (160) must equal Vertices length (801) for flat EdgeColor
In that case, you will need to set the 'EdgeColor' property of the 'bar_child' to a color specification or to 'none'. Add the following line just before the command that sets the 'CData' property:
set(bar_child, 'EdgeColor', 'r'); % red outlines around the bars
  4 Comments
Giuseppe Degan Di Dieco
Giuseppe Degan Di Dieco on 4 May 2021
Dear MATHWORKS Support Team,
you're awesome.
Your tip really helps me in solving the problem of creating multiple bar charts in a for loop.
Thanks.
Best.

Sign in to comment.

More Answers (2)

Andre Schultz
Andre Schultz on 3 Feb 2016
I don't know if you have way too many bars to plot, but you can plot them one at a time and set the colors one at a time. Like:
mydata=rand(1,5);
figure(1)
hold on
for i = 1:length(mydata)
h=bar(i,mydata(i));
if mydata(i) < 0.2
set(h,'FaceColor','k');
elseif mydata(i) < 0.6
set(h,'FaceColor','b');
else
set(h,'FaceColor','r');
end
end
hold off
Gets you:
  7 Comments
Ehsan
Ehsan on 21 Jun 2018
Another question is, how can you give this coloring to a grouped data? For example, you have "mydata=rand(2,5);" and you want to have all your numbers follow the same color format, while your data is grouped.

Sign in to comment.


Byron Caudle
Byron Caudle on 3 Apr 2018
Edited: Byron Caudle on 3 Apr 2018
There is also a way to do this as a stacked bar chart, using a stacked element for each color you want. Setup zero lengths for the bars you don't want, making it conditional depending on the data. Set the bar series colors after creation by capturing the output of the bar / barh function.

Products


Release

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!