How can I plot attached three interrelated stacked bars and separately style as well as label their partially recurring block components?

2 views (last 30 days)
Distelfink
Distelfink on 7 May 2022
Edited: dpb on 8 May 2022
Dear all,
I would like to visualize three decompositions by creating a graph with three stacked bar plots. I attach a schematic drawing of what I have in mind (and apologize for the format - I hope this makes it clearer than some lengthy explanation).
I have created stacked bar plots in the past, but what makes it complex / too hard for me is that
a) the blocks are interrelated across the decompositions A, B, C (e.g. block "b" turns up in decompositions A and C)
b) the separate styling and the labeling of the blocks
c) the labeling of the three stacked bars as "A", "B", "C".
Is there a way to insert the stacked bars next to each other, creating and labeling them independently but making matlab recognize the repeated occurrence of the block elements when it creates the legend?
I would be really grateful for any advice! Thank you

Accepted Answer

Distelfink
Distelfink on 8 May 2022
Extending dpb's answer below by using the user-written function applyhatch_plusC (along with its extension makehatch_plus, under the same link), I managed to get this result:
using the following code:
y = [5 2 0 4 0 0
5 0 3 0 3 0
5 2 0 0 3 1];
x=categorical({'A';'B';'C';'D'});
bar(x(1:3),y,'stacked')
legend(cellstr(['a':'f'].'),'Location','northeast')
xticks(x(1:3))
im_hatchC = applyhatch_plusC(gcf,{makehatch_plus('\\7',9),makehatch_plus('//7',9),makehatch_plus('//7',3),makehatch_plus('//7',9),makehatch_plus('\\7',9),makehatch_plus('//7',3)},[1 0 0;0 0 1;0 0 0;1 0 0;0 0 1;0 1 0]);
Not optimal (given the pixeled numbers, not only in attached image but in the original output as well - if somebody knows a solution to this please leave a comment) but possibly sufficient
  3 Comments
dpb
dpb on 8 May 2022
The problem is that to actually render the hatching patterns is a lot of calculations/work -- you have to have the boundaries of each area(*) and physically draw lines (programatically). It's much simpler to create a pattern and just replace the area at the cost of the resolution and so on.
When you create an area and then add more lines on it, the way HG works is that each and every one of those lines is a new, separate line handle unless all the coordinates are computed first and they're drawn as one line...either way, to legend the result is then an area and multiple lines/graphic objects handles, not a composite object that is the actual hatching pattern. Hence, legend() will create a new legend for each element; it doesn't know anything at all about the effect one is trying to create; they're all just independent areas/lines, each to be labelled on its own.
There needs, instead, to be an actual hatching object/property added to the base object space of HG objects/properties; it's the only way to ever make a really clean facility. Why it was not part of the base design when HG2 was invented is beyond my comprehension -- it's so fundamental a concept.
(*) And this is further complicated in case such as this where the X axis is a categorical variable for which one doesn't have the actual coordinates of the bars in the x-axis direction because while the line primitive does know about a categorical variable, there are only integral values from 1:N categories available in that coordinate system; there's no such thing as 'A' +/-80%(Difference 'B' - 'A') to use to limit the hatching line coordinates to within the specific bar.
At the user-code level one would have to resort to overlaying a second axes and doing the drawing on it instead because the CategoricalRuler axis object will only accept categorical values against the x-axis. So, while the hidden 'Face.VertexData' property does contain the same coordinates whether the x-axis is categorical or with the same data plotted against numeric 1:3 range, there's no way to make use of it if the axis is categorical; the CategoricalRuler object just won't let you pass anything else in. One would have to have access to the base properties at the internal level to be able to draw on the bars themselves.

Sign in to comment.

More Answers (1)

dpb
dpb on 7 May 2022
Edited: dpb on 7 May 2022
Use something like
y = [5 2 0 4 0 0
5 0 3 0 3 0
5 2 0 0 3 1];
x=categorical({'A';'B';'C';'D'});
bar(x(1:3),y,'stacked')
legend(cellstr(['a':'f'].'),'Location','northeast')
xticks(x(1:3))
to produce
Unfortunately, default colors are awful and we still don't have builtin hatching patterns so you'll have to work to set some less garish colors...
NB: the "trick" is each row in an array is a bar for a stacked plot; each column is the set of variable values for the bar; zero is a valid value (as is NaN for some special effects especially valuable).
NB Second: The extra category for the x axis to provide the room for the legend inside and then don't display the tick for it.
  7 Comments

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by