Add legend to plot colored by colormap function

314 views (last 30 days)
I am using currently making a plot where the color of the points is determined by a code (1-3) in the 3 column of the matrix. I can't seem to figure out how to get matlab to make a legend for this and not a colorbar. Since they're plotted as one thing the automatic legend function only includes one point. As it stands I've just been adding a legend in illustrator but it's a bit time consuming with lots of graphs and I'd prefer to have it done in matlab. Is it possible to either make a legend from scratch and specify each entry and label or get matlab to do it automatically? Thanks!
The code I am using and the figure are below:
x = [HL_conpor HL_perm HL_class];
colors = [0.8 0.8 0;
1 0.5 0
1 0 0
]; %
scatter(x(:,1), x(:,2),[], x(:,3),'filled')
set(gca, 'YScale', 'log')
xlabel('Connected Porosity(\phi_c)');
ylabel('Permeability (m^2)');
colormap(colors)
legend_labels = {'VDP1', 'VDP2', 'VDP3'};
legend(legend_labels, 'Location', 'Best');

Accepted Answer

Dave B
Dave B on 12 Aug 2021
Edited: Dave B on 12 Aug 2021
When you specify CData (the color input) for scatter, MATLAB uses colormapping to plot the data, and a colorbar to describe the mapping. Scatter is thinking of CData as continuous, but you're thinking of color as discrete.
There are two common approaches to solving this problem...
Problem case and fake data
x=randn(100,1);
y=randn(100,1);
c=randi(3,100,1);
tiledlayout(2,2)
nexttile;
scatter(x,y,30,c,'f')
colormap([1 0 0; 0 1 0; 0 0 1])
colorbar('Ticks',[4/3 2 8/3],'TickLabels',["Red" "Green" "Blue"])
title('Problem Version')
Solution 1: use hold on, make seperate scatter objects, and use colororder to define the colors (could also specify the color explicitly in each scatter as long as there's one color for each scatter):
nexttile(3)
hold on
scatter(x(c==1),y(c==1),30,'filled')
scatter(x(c==2),y(c==2),30,'filled')
scatter(x(c==3),y(c==3),30,'filled')
colororder([1 0 0;0 1 0; 0 0 1])
legend(["Red" "Green" "Blue"])
title("3 Scatters","(colororder instead of colormap)")
Solution 2: create some hidden scatters and pass them in to legend:
nexttile(4)
scatter(x,y,30,c,'f')
hold on
h=gobjects(3,1);
h(1)=scatter(nan,nan,'r','filled');
h(2)=scatter(nan,nan,'g','filled');
h(3)=scatter(nan,nan,'b','filled');
legend(h, ["Red" "Green" "Blue"])
title("3 Hidden Scatters")
For more info on colororder, see this documentation page

More Answers (1)

Scott MacKenzie
Scott MacKenzie on 12 Aug 2021
One approach is to do three scatters, one for each value in the 3rd column in your data. Here's the general idea using a modified version of your code:
x = [rand(25,1) rand(25,1) randi(3,25,1)];
colors = [0.8 0.8 0; 1 0.5 0; 1 0 1];
c1 = x(:,3) == 1;
c2 = x(:,3) == 2;
c3 = x(:,3) == 3;
scatter(x(c1,1), x(c1,2),100, 'filled');
hold on;
scatter(x(c2,1), x(c2,2),100, 'filled');
scatter(x(c3,1), x(c3,2),100, 'filled');
set(gca, 'YScale', 'log')
xlabel('Connected Porosity(\phi_c)');
ylabel('Permeability (m^2)');
colormap(colors)
legend_labels = {'VDP1', 'VDP2', 'VDP3'};
legend(legend_labels, 'Location', 'Best');

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!