Search code examples
matlabplotvisualizationdata-visualizationmatlab-figure

Color each section in a stacked bar plot differently


I have a stacked bar plot below:-

enter image description here

This was generated using:

b = barh(1:3,rand(3,2),'stacked');

Now i have a 3x2 cell C each cell element is a 1x3 RGB array.

C = cell(3,2);
for i = 1:3
  for j = 1:2
    C{i,j} = rand(1,3);
  end
end

There are 6 boxes in the figure and 6 corresponding colors. I want to fill these specified colors in the box. I thought using this method:

b(1).Parent.Parent.Colormap = C;

... but it did not work.

Can someone suggest how to draw custom stacked bar plots with the ability to control color of each bar segment? I don't think a tweaking of MATALB's bar command will help.


Solution

  • You need to duplicate and manipulate the graphics objects returned by the bar (or barh) function

    bar(y, 'stacked') returns one Bar graphics object for every column in y. The graphics objects have XData and YData fields which control the position and size of the bar sections. Since all sections from the same column share the graphics objects, you cannot manipulate the colors independantly.

    For example, if y is a 2x3 matrix, bar returns 3 graphics objects. Each objects has:

    • XData, a 1x2 vector containing bar indices
    • YData, a 1x2 vector with each element being the height of the section.
    • FaceColor, the color shared by all these sections

    My code replicates these graphics objects, so that instead of 3 graphics objects with 1x2 XData and YData fields, you have 6 graphics objects with 1x1 XData and YDatafields, each with a unique FaceColor.

    Start off with a normal bar or barh graph

    figure;
    n_bars = 2;
    n_sections = 3;
    
    %Initialize the bar graph with default coloring
    b = bar(rand(n_bars, n_sections), 'stacked');
    

    Now, make a new figure to hold the plot with the manipulated colors

    %Make new figure with new color scheme
    f = figure;
    a = axes('Parent', f);
    
    %Colors
    C = rand(6, 3);
    

    For each graphics object from the original, make two copies.

    for jj = 1:n_sections
      %Duplicate the bar graphics object results 
      section1 = copyobj(b(jj), a);
      section2 = copyobj(b(jj), a);
    
      % Remove one of the bars from each section
      section1.YData(1) = 0;
      section2.YData(2) = 0;
    
      %Change the color
      section1.FaceColor = C(sub2ind([n_bars, n_sections], 1, jj), :);
      section2.FaceColor = C(sub2ind([n_bars, n_sections], 2, jj), :);
    end
    

    Before and After!

    Default bar plot Modified bar plot