How do I make a legend for data organized into colours in a bar plot?
32 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Dan Hallatt
am 8 Mär. 2019
Kommentiert: Dan Hallatt
am 11 Mär. 2019
Hello, I have data (see attached figure) which is grouped together by colour. I would like to have a legend that which explains what each colour grouping is defined by. I can only find legend creation questions about creating legends on the actual x-axis data, instead of the colour by which I organized it.
Is there a way to do this? I organized my data by colour as follows:
for i = 1:length(Names)
switch Names(i)
case{'Pu','Am','Np','Cm'}
Yield.CData(i,:) = [255 0 0];
case{'Mo','Ru','Tc','Rh','Zn','Ga'}
Yield.CData(i,:) = [0 255 0];
case{'Ce','Nd','Eu','Sm','Sc','Y','La'}
Yield.CData(i,:) = [255 255 0];
case{'Li','Na','K','Rb','Cs','Fr'}
Yield.CData(i,:) = [0 0 0];
case{'O','Xe','Te'}
Yield.CData(i,:) = [255 255 255];
end
end
If someone could provide an answer or some insight I would greatly appreicate it.
~ Dan
1 Kommentar
Akzeptierte Antwort
dpb
am 9 Mär. 2019
OK, with your data file...
[Yield,Elements] = xlsread('test.xlsx');
[YS,iY]=sort(Yield,'descend'); % index to plot by size
FigureName = '';XaxisLabel ='Element';YaxisLabel='Yield (atomic %)';
hF=figure('Name',FigureName,'color','white');
hBY = bar(YS); % use different, identifiable variable for handle
hBY.FaceColor = 'flat';
for i = 1:length(Elements)
switch Elements{iY(i)} % get in sorted order
case{'Pu','Am','Np','Cm'}
hBY.CData(i,:) = [255 0 0]; % red for actinides
case{'Mo','Ru','Tc','Rh','Zn','Ga'}
hBY.CData(i,:) = [0 255 0]; % green for noble metals
case{'Ce','Nd','Eu','Sm','Sc','Y',}
hBY.CData(i,:) = [0 0 255]; % blue for lanthanides (R.E.E.)
case{'Li','Na','K','Rb','Cs','Fr'}
hBY.CData(i,:) = [0 0 0]; % black for alkali-metal halides
case{'O','Xe','He','Ne','Ar','Kr',}
hBY.CData(i,:) = [255 255 255]; % white for non-metals
end
end
hAx=gca; % axes handle for munging with
hAx.XTick=1:numel(Y);
hAx.XTickLabel=Elements(iY);
hAY.YAxis.TickLabelFormat='%0.3f'; % set consistent format string
xlabel('Element','FontName','Optima','FontSize',10);
ylabel('Yield (atomic %)','FontName','Optima','FontSize',10);
title('Yield by Element Classification','FontName','Optima','FontSize',16);
% Now add dummy bar plot to make legends match colors
hold on
% colors -- desired color for each type/class
%co=get(groot,'defaultAxesColorOrder'); % get current axes color order
colors=[[1 0 0]; ... % red for actinides
[0 1 0]; ... % green for noble metals
[0 0 1]; ... % blue for lanthanides (R.E.E.)
[0 0 0]; ... % black for alkali-metal halides
[1 1 1]]; % white for non-metals
nColors=size(colors,1); % make variable so can change easily
labels={'Actinide';'Noble metal';'Lanthanide';'Alkali halide';'Non-metal'};
hBLG = bar(nan(2,nColors)); % the bar object array for legend
for i=1:nColors
hBLG(i).FaceColor=colors(i,:);
end
hLG=legend(hBLG,labels,'location','northeast');
produces
4 Kommentare
Weitere Antworten (1)
dpb
am 8 Mär. 2019
Bearbeitet: dpb
am 9 Mär. 2019
The bar plot/object in Matlab is a really, Really, REALLY difficult thing to work.with, unfortunately.
A single bar plot has only one bar object as you've drawn it above and, therefore, you can only assign one legend string because there is only a single graphic object on the plot to assign the legend to.
You can "fake" it by creating a hidden grouped bar with two rows by the number of columns that you have colors, in this case five (5) and then assigning those bar objects the desired colors and use legend() on them.
A dummy example with the "real" data being five bars and four dummy colors
hB=bar(abs(randn(1,5))); % generates one bar handle with five bars
hB.FaceColor='flat'; % ready to set color by bar w/ CData
hB.CData(1,:)=[255 0 0]; % first and
hB.CData(3,:)=[255 0 0]; % third red
hB.CData(2,:)=[0 255 0]; % second green
hB.CData(5,:)=[255 255 255]; % fifth white, leaves fourth default
hold on % set hold state to add onto plot
hBB=bar(nan(2,4)); % now create the dummy four bar handles
hBB(1).FaceColor=[1 0 0]; % FaceColor is normalized 0, 1 instead of rgb -- red
hBB(2).FaceColor=[0 1 0]; % green
hBB(3).FaceColor=[0 0 1]; % blue
hBB(4).FaceColor=[1 1 1]; % white
hLG=legend(hBB,'A','B','C','D','location','northwest'); % write legend for the colored bars
The above creates the following figure--
I've railed for years about bar; TMW really should totally redesign a new replacement that isn't so difficult to use for obvious needs.
6 Kommentare
dpb
am 9 Mär. 2019
Bearbeitet: dpb
am 9 Mär. 2019
I tried to recast the problem to use a 2D array to generate an array of bar handles to color but BAR() is just too inflexible--when you create a grouped bar, then it forces the center of each group to the location of the row index in the input array and won't let you locate individual bars.
The only alternative to the above "trick" I see is to create N bar plots, each of which then contains only the desired elements for the given set, but has NaN for all the other elements. Building those arrays is also a convoluted mess of coding.
All in all, my previous remarks still hold--TMW needs to introduce a whole new barplot routine that one could do something with.
I did rewrite your code a little and posted a second answer...but yours will work with just the addition of the hold on line I didn't get pasted in the example and fixing up some of the labels and so on. I'm not sure what your intent was there...
Siehe auch
Kategorien
Mehr zu Data Distribution Plots finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!