Grouped Bar Plot with NaN GAP

22 visualizaciones (últimos 30 días)
Manuel Lauber
Manuel Lauber el 16 de Feb. de 2021
Editada: dpb el 19 de Feb. de 2021
Hey there,
i am having a problem concering grouped bar charts. When i have NaN or Zero values in the matrix, the Plot creates several Gaps between the bars with values.
How can i group the valued bars together without changing the colormap ?
Ty in advance.
  3 comentarios
Mario Malic
Mario Malic el 16 de Feb. de 2021
I removed the answer as the colors are not the same and it's not a proper answer. You will have to create a vector with CData to match the colors, accounting for NaNs in vectors. This will cause also issues in legend displaying 5 entries, instead of 3.
bar(1, [1 2 3])
hold on
bar(2, [4 6])
dpb
dpb el 16 de Feb. de 2021
As Cris notes, this is documented behavior and I agree with his assessment this would generally be the expected behavior of zero data being shown where is in relationship to each group and consistent bar coloring across groups.
There is no indication in the MATLAB bar() function, however, of there being any difference between a NaN and a 0; and those may well be entirely different things in some contexts. Perhaps that's the OP's underlying issue here.
One solution might be to label the missing bar location with a text string <Missing> or somesuch; this is relatively easy now that TMW has provided the 'XEndPoints' property that lets one know where to write such text.
hB=bar(f); % OP's bar, save handles
hTxt=text(hB(2).XEndPoints(2),0.1,'<IsMissing>','Rotation',90,'Color',hB(2).FaceColor); % write for the one NaN
ylim([0 8])
results in
One obviously could write code to locate where NaN are in the input array for the general case if an idea were to suit.
Alternatively, if really do want to collapse the bars, then again a generalized routine to implement Mario's idea above is also doable; one there has to retrieve the colors of the full-size group to match those with the missing bar(s).

Iniciar sesión para comentar.

Respuestas (1)

Adam Danz
Adam Danz el 16 de Feb. de 2021
Editada: Adam Danz el 19 de Feb. de 2021
I agree with everyone's comments under you question; the bar plot is much clearer with the gap.
  • Both the color and bar order, including the spacing, indicates groups of data. If bars are shifted, color and spacing no longer agree making is possible for perceptual grouping errors.
  • The missing bar indicates missing data and missing data is informative.
Additionally, moving the bars isn't as easy as specifying the x-location of the bars. You also have to make sure that the colors indicate the correct groups, that the xticks makes sense, that the bars groups are centered within the group, and that the bar widths are equal and some of these steps are more difficult than you may think.
Setting the color can be done by setting FaceColor to flat and setting the CData for each bar within each group.
Bar widths are really tricky because the BarWidth propery is releative, not absolute. So if one bar group has 3 non-nan values and another has 2 non-nan values, the bars will have different widths even though the BarWidth is set to 0.8 for all bars.
XTicks have to be set manually when specying x locations for bar, or you could remove them all together. Try plotting this example and you'll see that group #2 does not have an xtick (r2020b) bar(1,[1 2 3]); hold on; bar(2,[1 2 3]);
Centering the bar groups can become especially difficult using bar(). Consider groups of 4 bar plots and one group is missing 3 values leaving 1 bar. You may think you can plot it directly on the x-tick but that group of bar plot will only have 1 bar while the others have 4 which causes the width-problem I mentioned above. You could pad the vector is NaNs so you have 4 value and a bar width that matches the other groups but that can't be centered.
Some of these problems can be fixed by using histogram instead of bar but there's quite a lot of work to do to make that happen and it will still not look as clean as what you already have.
Here's an example using bar that shifts all non-nan bars leftward and maintains their original colors and widths but some groups are not centered.
% Bar data: This is the only "input" to the script below
data = [1 2 3 4; 1 nan nan 4; nan 2 nan 4; 1 nan 3 nan; 4 3 2 1]+2
data = 5×4
3 4 5 6 3 NaN NaN 6 NaN 4 NaN 6 3 NaN 5 NaN 6 5 4 3
%%%%%%%%%%%%%%%%%%
clf()
subplot(2,1,1)
h1 = bar(data,'grouped');
title('Original Data')
% Move NaNs to the left
numIdx = ~isnan(data);
numIdxSort = cell2mat(arrayfun(@(i){sort(numIdx(i,:),'descend')},1:size(numIdx,1))');
dataNan = nan(size(data'));
barVals = cell2mat(arrayfun(@(i){data(i,~isnan(data(i,:)))},1:size(data,1)));
dataNan(numIdxSort') = barVals;
% Get colors
colIdx = ones(size(numIdxSort'));
colIdx(numIdxSort') = cell2mat(arrayfun(@(i){find(numIdx(i,:))},1:size(numIdx,1)));
cmap = lines(size(data,1)); % Use any colormap
barCMaps = arrayfun(@(i){cmap(colIdx(i,:),:)},1:size(colIdx,1))';
subplot(2,1,2)
h2 = bar(dataNan', 'grouped');
set(h2, 'FaceColor', 'Flat')
set(h2,{'CData'}, barCMaps)
title('Bars shifted')
If the spaces between bars are causing perceptual grouping problems, you could add divider lines,
figure()
subplot(2,1,1)
h1 = bar(data,'grouped');
title('Original Data with divider lines')
arrayfun(@xline,h1(1).XData(2:end)-.5)
subplot(2,1,2)
h2 = bar(data,'grouped');
title('Original Data with divider labels')
labs = compose('Group %d',1:size(data,1));
arrayfun(@(x,str)xline(x,'k-',str,'LabelHorizontalAlignment','left','FontSize', 8),h1(1).XData+.55,string(labs));
xlim([.5, size(data,1)+.55])
  3 comentarios
Adam Danz
Adam Danz el 19 de Feb. de 2021
Yeah, it's high time for patterned fills. Here's an image from the first version of Excel in 1985.
dpb
dpb el 19 de Feb. de 2021
Editada: dpb el 19 de Feb. de 2021
And, undoubtedly the recent changes to legend will have broken the patches I made back then. Fortunately, the need went away again to the extent anyways, that wasn't forced into having to have.
<https://www.mathworks.com/matlabcentral/answers/100919-how-do-i-fill-a-patch-object-with-a-pattern-such-as-diagonal-lines-or-a-texture-map-in-matlab-r202?s_tid=answers_rc1-3_p3_Topic>

Iniciar sesión para comentar.

Categorías

Más información sobre Bar Plots en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by