# How do I get a "tabular" legend?

94 views (last 30 days)
820408 on 10 May 2017
Answered: Steven Lord on 23 Mar 2018
In MatlabR2015b, I am plotting a 2D scatter plot of "Performance" that is a function of two independent variables "Active agent" & "Temp". I have 3 Active Agents and 4 Temps. In scatter plot, I am using a 12 colors, one for each (ActiveAgent,Temp) pair. I want to customize legend so that it appears in a tabular form like (C1 would be like marker 'o' in its respective colors)
Temp1 Temp2 Temp3 Temp4
Agent1 C1 C2 C3 C4
Agent2 C5 C6 C7 C8
Agent3 C9 C10 C11 C12
How can I do this?

Kelly Kearney on 10 May 2017
You can hack your way to a solution with my legendflex function. It's designed to make gridded-style legends like this, though unfortunately doesn't include the row/column label function yet (I'll keep that in mind for an enhancement, though... shouldn't be too hard to add).
Scatter only creates a single object to label, so to get individually-colored marker for a legend, you can create some invisible line objects:
% Data
nrow = 3;
ncol = 4;
ngrp = nrow*ncol;
x = rand(100,1);
y = rand(100,1);
group = ceil(rand(100,1)*ngrp);
datalabel = strtrim(cellstr(num2str((1:ngrp)', 'C%d')));
rowlabel = strtrim(cellstr(num2str((1:nrow)', 'Agent%d')));
collabel = strtrim(cellstr(num2str((1:ncol)', 'Temp%d')));
% Plot
scatter(x,y,[],group);
cmap = parula(ngrp);
colormap(cmap);
set(gca, 'clim', [0 ngrp] + 0.5, 'ylim', [-0.5 1.5]);
hln = line(nan(2,ngrp), nan(2, ngrp), 'marker', 'o', 'linestyle', 'none');
set(hln, {'color'}, num2cell(cmap,2));
% A regular legend to show the hidden-marker idea
hplain = legend(hln(:), datalabel(:));
export_fig('leggrid1', '-png');
delete(hplain);
There are two ways I can think of to get the grid layout. One is to add extra no-marker objects for both the row and column labels. The second is to add extra markers just for the row labels, and create multiple legends with legendflex's title property for the column labels. The latter centers the column titles over the label and object together, which I prefer, but it means you have to keep the box off (which may or may not work for your data):
% Option 1: add extra objects for row/column labels
hr = line(nan(2,nrow), nan(2,nrow), 'linestyle', 'none');
hc = line(nan(2,ncol+1), nan(2,ncol+1), 'linestyle', 'none');
allobj = [hc'; [hr reshape(hln,nrow,ncol)]];
alllbl = ['-' collabel'; [rowlabel reshape(datalabel,nrow,ncol)]];
hleg1 = legendflex(allobj(:), alllbl(:), 'nrow', nrow+1, 'xscale', 0.5);
% Option 2, multiple legends with titles
allobj = [hr reshape(hln,nrow,ncol)];
alllbl = [rowlabel reshape(datalabel,nrow,ncol)];
ttl = ['-' collabel'];
for ii = (ncol+1):-1:1
if ii == (ncol+1)
hleg2(ii) = legendflex(allobj(:,end), alllbl(:,end), 'ref', gca, ...
'anchor', {'se','se'}, 'buffer', [-10 10], 'xscale', 0.5, ...
'box', 'off', 'title', collabel{end});
else
hleg2(ii) = legendflex(allobj(:,ii), alllbl(:,ii), 'ref', hleg2(ii+1), ...
'anchor', {'sw','se'}, 'buffer', [0 0], 'xscale', 0.5, ...
'box', 'off', 'title', ttl{ii});
end
end
820408 on 11 May 2017
Thank you. This is what I was looking for.

Shane L on 23 Mar 2018
If you are looking for a code that is built to create a "tabular" legend, my GridLegend function on the File Exchange will create a "legend" (actually a legend-like axis) with row and column labels. My GridLegend function is not as versatile as Kelly's legendflex function, but it will give you a "tabular" legend with no additional work on the user's end.

Steven Lord on 23 Mar 2018
In release R2018a, you can now control how many columns your legend has.
% Generate data and set up the axes
x = linspace(0, 2*pi, 500);
axis([0 2*pi -8 8]);
hold on
% Plot 8 sine curves, naming each n*sin(n*x) for legend purposes
for n = 1:8
plot(x, n.*sin(n*x), 'DisplayName', sprintf('%d*sin(%d*x)', n, n));
end
% Turn on the legend
L = legend('show');
% Make it 2-by-4 instead of 8-by-1
L.NumColumns = 4;
This isn't exactly what the original poster asked for, but it's close.