How do I make a legend for data organized into colours in a bar plot?

조회 수: 65 (최근 30일)
Dan Hallatt
Dan Hallatt 2019년 3월 8일
댓글: Dan Hallatt 2019년 3월 11일
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

채택된 답변

dpb
dpb 2019년 3월 9일
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');
producesuntitled.jpg
  댓글 수: 4
dpb
dpb 2019년 3월 11일
I can be contacted via contributors link if care to...

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

dpb
dpb 2019년 3월 8일
편집: dpb 2019년 3월 9일
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
Dan Hallatt
Dan Hallatt 2019년 3월 9일
oh wow I should have thought of that. Thank you so much, this works well. I really appreciate your help dpb!:)
dpb
dpb 2019년 3월 9일
편집: dpb 2019년 3월 9일
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...

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 2-D and 3-D Plots에 대해 자세히 알아보기

제품


릴리스

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by