Editor's Note: This file was selected as MATLAB Central Pick of the Week
As of Matlab 2018a, legend() now supports columns, so function will no longer be maintained: https://www.mathworks.com/help/matlab/ref/legend.html#d117e809522
Updated 9/8/16: Added new legend positions (e.g. northeastoutside) and better positioning.
usage:
numlines = 5;
r = rand(10,numlines);
plot(r);
columnlegend(2, cellstr(num2str([1:numlines]')), 'location', 'northeastoutside');
PRINTING: If you want to print the figure, you'll have to use a command line printer (e.g. export_fig) as the File->Print option embedded in the figure resets the figure properties including the legend
Simon Henin (2021). simonhenin/columnlegend (https://github.com/simonhenin/columnlegend), GitHub. Retrieved .
Inspired: freelegend(hline,hax,hf,str,posi,varargin), gridLegend - a multi column format for legends
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Create scripts with code, output, and formatted text in a single executable document.
it can not work
As of Matlab r2018a, multi-column legends are supported by Matlab's built-in legend function.
To learn how to edit properties of the legend produced by this function in Matlab releases prior to r2018a, see the link below. Special thanks to Simon Henin for leading the initiative in multi-column legends.
https://www.mathworks.com/matlabcentral/answers/499402-legend-properties-of-columnlegend#answer_409211
at last i found the error; it doesnt work when there is a patch object in the legend.
@Hamdullah
Seems to work fine for me:
figure; plot(rand(10, 6));
legend();
savefig('test.fig');
close;
h=openfig('test.fig','visible');
hleg=findobj(h,'Type','Legend');
str=hleg.String;
columnlegend(3,str);
FYI. As of Matlab 2018a, legend() now supports columns, so I will no longer be maintaining this code:
https://www.mathworks.com/help/matlab/ref/legend.html#d117e809522
it does not work on handled figure; it extends the legend rather than spliting it...
example:
h=openfig('3503_rhv.fig','visible');
hleg=findobj(h,'Type','Legend');
str=hleg.String;
columnlegend(3,str);
Could anyone resolve this issue (that has already been posted here by few users):
Index exceeds matrix dimensions.
Error in columnlegend (line 110)
sheight = vertices_1(2,2)-vertices_1(1,2);
THANK YOU
I suggest the bugfix
location = lower(varargin{i+1});
Currently it does not allow 'south' to be written 'South', as Sarah Pasternak(30 Nov 2017) has pointed out already.
Otherwise, thanks for the great submission.
Great helper! However, it seems that the legend box doesn't render right when altering the padding.
@Mingxuan: Use the parameter 'fontname' (should be lower case)
how to change fontname?
You saved my intern's life using Matlab R2017b ^^
Hi, this is really great. But I think there is a bug. It can't be used with errorbar.
This function would get 5 stars, the only problem is that you cannot easily alter the spacing between columns. Would it be possible to add this functionality please?
@Simon Thanks for the reply.
I think the "padding" input is only for reducing vertical spaces between entries.
I actually would like to reduce the room between the marker and the instruction text in each entry.
Will it be possible?
Thank you.
@Baolei
There is a "padding" input option that allows you to add some extra padding between legend elements. You can use negative padding to bring entries closer together.
It's really useful! Thank you, Simon.
Is there a way to minimize the spacing between the sign and the text and/or between columns? It will be very helpful since most people use this columnlegend to save the page layout.
Looking forward to your responses.
@GreenPiece
This seems to be a bug with the legend function when extra input arguments are passed. In version <2017a, the fontsize doesn't render, and the handles to legend objects are lost. I suggest modifying the fontsize after the call to the function. Something like:
plot(rand(10, 5));
[handle,legend_objects]=columnlegend(3, cellstr(num2str([1:5]')));
pause(0.1); % <- note the pause here. It is required to make sure the legend has fully rendered
set(findall(legend_objects, 'type', 'text'), 'fontsize', 20);
Hope this helps
@Simon Henin
I am using Matlab 2016a.
@GreenPiece
I can't seem to reproduce the issue:
plot(rand(10, 5));
columnlegend(3, cellstr(num2str([1:5]')), 'location', 'southwest', 'fontsize', 30);
works fine for me. What version of MATLAB are you using?
I think the problem from this line:
if ~isempty(extravars),
[legend_h,object_h,plot_h,text_strings] = legend(str, extravars{:});
Fof example, If I set
legend_h = legend(str, extravars{:},'FontSize',22);
I can change the font size but if
[legend_h,object_h,plot_h,text_strings] = legend(str, extravars{:},'FontSize',22);
It would not work. Can you help to explain why?
@Lukas
Just pass fontsize as a name-value argument to the function:
l = columnlegend(2, str, 'fontsize', 18);
Hi Simon.. nice job, but I think the FontSize doesnt work properly or is it just my fault...
l = columnlegend(2, str);
l.FontSize = 18;
The columns will expand the size but the FontSize doesnt really change..
@Matthew
You need to use the print command from the command line (print('myfigure.png', '-dpng') ) or another command line printer like export_fig. Using File->save as, causes strange rendering problems.
Just as an edit to my last comment, the LiveFigure doesn't show the legend as having two columns, but if I run the script from a .m file the output is the same as the saved figure (two columns bad spacing). Additionally, it looks like the 'boxon' parameter puts the box in the right place, but not the legend entries...
Simon,
I just realized that when I save the figure, the legend has two columns (the spacing is poor). However, just viewing the figure it does not have two columns.
https://drive.google.com/open?id=13EtSGPEyS7thXUbFpNTCWnEUD0-gnRas
Best,
Matthew
@Matthew
Do you have a code sample and/or image of the result? I'm not quite getting the issue, so some sample code would be helpful.
@King
Are you using a latex text interpreter? This may override the fontwieght property.
Hi Simon,
This code looks to be exactly what I am looking for, but when I try to implement it the legend seemingly scoots over a column, but none of the entries occupy the space of the second column. I tried doing some debugging, but I couldn't seem to find where the fix is needed. In the 'line' type, the object_h x/ydata are being updated, but nothing moves.
Any help on this?
Best,
Matthew
Hi Simon,
I forgot to say that I also tried your suggestion before: columnlegend2(2, legend,'fontweight','bold','boxon'), where legend is the list of my names in a cell. However, the legend is still shown as without font weight. Logically speaking, I know it should work, but still couldn't figure it out what is the cause of this. Is there another trick or way around this problem that you can think of?
Thanks!
@King
Simply pass it as an argument. The function takes the same Name-Value pairs as regular legend. So,
columnlegend(2, {'label1', 'label2', 'label3'}, 'fontweight', 'bold');
Hi, I cannot change the font weight of the legend. I use set function to allocate the font weight for the legend_h: set(legend_h, 'FontWeight', 'bold'). It didn't work.
I also defined font weight as a case at the beginning of the code, but it's still not happening. Can you give me some hints, so I cane change the font weight.
Thanks!
@Lisa
I just updated the script to handle this special case of mixing line/errorbar plots. Hope it works for you.
Hi Simon,
very nice addon! Sadly when I combine an errorbar plot and some norml plots, it doesn't work for me and I get the error message:
Index exceeds array bounds.
Error in columnlegend (line 119)
child2 = child2(2);
What am I doing wrong?
------------------------------------------------------------------------------
My example code:
x=1:10;
y1=x.^2;
y2 = repmat(y1,numel(x),1);
leg_str = cell(numel(x),1);
figure(22)
errorbar(x,y1,sqrt(y1));
leg_str{1} = 'errorbar';
hold on
for i=1:numel(x)
plot(x,y2);
leg_str{i+1} = sprintf('plot %u',i);
end
columnlegend(2,leg_str)
------------------------------------------------------------------------------
Hi Simon, if I use your function in a Live Script it doesn't work, but if I cut and paste the code (or use your example from the function comments) into the command window it works.
plot(bsxfun(@times, [0:9]',[1:10]));
columnlegend(3, cellstr(num2str([1:10]')), 'location','northwest');
@M G (Laura)
It should work with errorbar plots as well. As an example, try:
figure;
errorbar(1:3, rand(3, 1), rand(3, 1)); hold on;
errorbar(1:3, rand(3, 1), rand(3, 1));
columnlegend(2, {'ErrorBar 1', 'ErrorBar 2'});
Hi Simon,
well I think it's because I am using errorbar and not plot. With plot it works totally fine. Is there a possibility to use errorbar instead of plot?
Thanks, Laura =)
Hi Simon,
Thank you for the nice code. It works perfectly for my purpose. I noticed maybe a small bug or could be because I'm working in Matlab R2011. When using the saveas command it is possible to properly save the plots and legends made using this command but when manually saving the figure as a jpg file, the legend is reordered vertically. An easy work around is to save the figure programmatically but I just wanted to inform you on the (minor) issue with the code.
Kind regards,
Nathan
PS: quick example:
plot(magic(3));
columnlegend(3,{'Plot A', 'Plot B', 'Plot C'})
saveas(gcf,'Trial1.jpg');
saving the same figure manually as Trial2.jpg shows the difference I am talking about.
@Simon, it's really amazing, thanks again!
Thanks a lot, Simon!
@Brain
Fixed the bug. You can re-download for functional version.
By the way, the Matlab version is 2017b.
Thanks
Hi Simon, thanks for providing the codes. However, it seems not to work...
>> plot(bsxfun(@times, [0:9]',[1:10]));
columnlegend(3, cellstr(num2str([1:10]')), 'location','northwest');
Cell contents reference from a non-cell array object.
Error in columnlegend (line 67)
[legend_h,object_h,plot_h,text_strings] = legend(str, extravars{:});
Thanks!
@Frederick, @Auryn_
I've updated the function to support errorbar plots and allow for optional inputs supported by legend, such as 'fontsize'.
For example:
errorbar(rand(10, 5), rand(10, 5));
columnlegend(3, {'1', '2', '3', '4', '5'}, 'location', 'northoutside', 'fontsize', 18);
Hi!
I am trying to plot multiple lines with the function errorbar (it works). Then I want to use multicolumn for the legend, but this does not work. It works if I use plot instead of errorbar though.
This is the error I receive when using columnlegend (which works when using plot instead of errorbar):
Error using matlab.graphics.primitive.Group/get There is no vertices property on the Group class. Error in columnlegend (line 97) vertices_1 = get(child, 'vertices');
Hi, is there a way to adjust font size in columnlegend?
I solved it already Simon, I just set the 'padding' to zero :)
Function works perfect, many thanks for sharing it
@Selim
You seem to be using a function (maxfig), which maximizes the axes within the figure window. Does it work if you don't use maxfig?
Hi Simon
When setting 'Location' as 'SouthOutside', part of my legend is not shown because it is below the graph limits. There is also a big blank gap between the bottom of the x axis and the top of my legend. Could you help please?
Many thanks
Victor
Hi Simon,
i m using Matlab2017b
maxfig(V_rT,1)
set(0,'CurrentFigure',V_rT);
columnlegend(6,legend_str,'Location','Southoutside');
I got an error saying:
Error using matlab.graphics.axis.Axes/set
Error setting property 'Position' of class 'Axes':
Width and height must be greater than or equal to 0
Error in columnlegend (line 205)
set(gca, 'position', [fig_pos]-[0 -pos(4) 0 pos(4)]);
Thanks,
Selim
worked just fine; awesome! thanks
Hi Simon,
Do you know how to get around the following error?
The name 'vertices' is not an accessible property for an instance of class 'hggroup'.
Thanks,
Negin
@Tiago
I cannot seem to recreate your issue. If I do:
plot(rand(100, 5)); [legend_h,object_h]=columnlegend(3, {'h_1' 'h_2' 'h_3' 'h_4' 'h_5'}, 'Location', 'Southoutside');
Seems to work fine. What version of MATLAB are you using? What is the exact error from MATLAB? Are their any details about the legend entries, e.g. they are very long text, or include special characters?
Dear Simon,
I got a function to make plots with the desired format I want.
function out = plotgeral(Y,Y1,Y2,Y3,Y4,Y5,eixoX,eixoY,titulo,legenda,legenda1,legenda2,legenda3,legenda4,legenda5)
where legenda to legenda 5 are the names of the legend for each Y I plot.
i made :
legend([out out1 out2 out3 out4 out5],legenda,legenda1,legenda2,legenda3,legenda4,legenda5,'Location','SouthOutside','Orientation','Vertical');
but it is to big, i changed to horizontal and it is to large, so i wanted to place the legend under 2 ou 3 columns.
So in my function i called yours but it doesnt work, i wrote this:
str = {legenda,legenda1,legenda2,legenda3,legenda4,legenda5}
columnlegend(3,str,'Location','Southoutside','boxon');
I got an error saying the position values must be between 0 and 1.
Thank you simon
@Amra
You could just pass the first two legend entries:
line_handles = plot(rand(100, 10));
columnlegend(2,{'a','b'}); % this will only add the first 2 lines to the legend.
Dear Simon, how to use the subset entry legend on this function? for instance, I just want to show L1 and L2 in legend entry. I used this:
columnlegend(2,[L1 L2 L3 L4 L5],{'a','b', 'c', 'd','e'},'Location','northeast');.. But this not work. Thank you
@ Deepak
Not at this time, but you can do the same thing by just setting the current focus to your axes. e.g. axes(AX); cloumnlegend(...);
@ Namira
You need to pass a cell array of legend strings: columnlegend(2, {'a', 'b', 'c', 'd', 'e', 'f', ‘g’,’h’,’i’,’j’}, 'location', 'northeastoutside')
Dear Simon,
Is there any way to set input argument as specific axes. I want to give legend to specific axes like "legend(target,__)". I am using "plot(AX,...)" plots into the axes with handle AX. Thank you.
@ Dear Simon,
Thank you so much. It's working now. I am new in Matlab. I have one more question. I have 10 plots in a figure. When I was trying to use column legend in my code for example
columnlegend(2, 'a', 'b', 'c', 'd', 'e', 'f', ‘g’,’h’,’i’,’j’, 'location', 'northeastoutside')
It shows just first legend in the graph.
Can you please help me to solve this problem?
@Namira
Your script cannot find the function. Place columnlegend.m somewhere in your MATLAB path (e.g. in same folder as script)
I am using R2016b. When I try to use this command it shows error
Undefined function or variable 'columnlegend'.
Error in untitled (line 4)
columnlegend(2, cellstr(num2str([1:numlines]')), 'location', 'northeastoutside');
Can anyone help me regarding this issue?
Hi Simon,
Thanks a lot for this code! I've had one issue with it though: when using fplot instead of plot, object_h only has numlines elements, and so your code crashes. Not sure many people use fplot, but just letting you know.
Best,
Thomas
Dear Simon,
Well, I figured out the mistake, so need to worry here. I forgot {'object1,object2} - the clams around the objects. Stupidy when working in MATLAB at 22:00 :D
It was awesome, thank you!
Best Regards,
Mads
@Janine
Use drawnow before changing the interpreter to make sure everything has finished rendering:
plot(rand(100, 4)); [legend_h,object_h]=columnlegend(2, {'h_1' 'h_2' 'h_3' 'h_4'});
drawnow;
set(findall(object_h, 'type', 'text'), 'interpreter', 'none')
Dear Simon,
how can I set the Interpreter to 'none'? Whatever I do, I cannot seem to disable the tex interpreter.
The reason behind that is that I have legend entries with underscores "_" which are interpreted as subscripts.
The typical way does not work: set(legend_h,'Interpreter', 'none')
I do not know why. The other way does work: legend(str,'Interpreter', 'none')
But then your code does not work.
Thanks in advance and thanks for the function.
@betsy456
This seems to be a bug with MATLAB's builtin legend function. When returning handles, it removes any alpha formatting.
For example, try (the second legend call will not render the alpha transparency):
----
figure; plot(1:10, rand(10, 5), 'color', [1 0 0 0.1]); legend( {'1', '2', '3', '4', '5'});
vs.
figure; plot(1:10, rand(10, 5), 'color', [1 0 0 0.1]); [a,b,c]=legend( {'1', '2', '3', '4', '5'});
-----
I will work on a workaround in the function for the next release. For now, here's a quick hack if you are using a common alpha value:
% make a plot with alpha lines
alpha = 0.1;
figure; plot(1:10, rand(10, 5), 'color', [1 0 0 alpha]);
[legend_h,object_h]=legend( {'1', '2', '3', '4', '5'});
% use the legend handles, and apply alpha to line objects
bb = findall(object_h, 'type', 'line');
for i=1:length(bb), set(bb(i), 'color', [bb(i).Color alpha]); end
Hi, this code is great, but I just wondered if there was a way of putting partly transparent colours in the legend. In my bar chart I have some bars of a certain colour, and some of the same colour, but with 'FaceAlpha' at 0.5, so they are partially transparent. In the legend, both of these appear as the full colour, is there any way to remedy this?
Thanks
@Linda
Just like you would with the built-in legend command, like:
% plot 4 line
plot(rand(100, 4));
% add legend with custom labels
columnlegend(2, {'x','4','g','6'});
how so you get your own input arguments so that in de legend it doesn`t display: 1,2,3, 4,5...... but someting like x,4,g,6
@Jamesa
You just need to pass the handles of the line objects you would like to use in the legend. e.g.:
% plot 8 different lines and return the handles
h = plot(rand(100, 8));
% add columnlegend and provide the handles of line objects 5-8
columnlegend(2, h(5:8));
Hi! This is awesome! One quick question: does this have the functionality to skip legend entries? If I have, for example, 8 lines plotted, but I only want to have legend entries/symbols for the last four lines?
For those who are interested in getting Latex interpreter for the Legend. Change the line
[legend_h,object_h,plot_h,text_strings] = legend(str);
to
[legend_h,object_h,plot_h,text_strings] = legend(str,'interpreter','latex','FontSize',12);
and put $$ at appropriate locations when making the call, e.g.,
columnlegend(2, {'$f(z)$'}, 'location', 'northeast');
Thank you for sharing this code.
I think I found a tiny bug though.
In line 41, the steps in the for loop shouldn't be 1 instead of 2? The 2 jumps are included in the cases when needed.
The 'boxon' and 'boxoff' doesn't require the step to be 2, for example.
Also, any tips on how to include a latex interpreter for the legends?
Thanks
Thank you for sharing the code
Thanks for the nice code.
I want to put the legend in the southwest, can you list the objects of legend like this:
9 10
5 6 7 8
1 2 3 4
There is error in line 138,' There is no ydata property on the Group class', there is scatter and plot in my figure
Hi Simon,
I can't seem to find your function anywhere on File Exchange. Is there somewhere other than this page where it can be located?
Thanks, Chov
The function does not appear to be compatible with figures produced using scatter.
Thanks for this code!
Small bug fix:
current code only accepts locations where 'south' is in lower case, unlike "legend" command which is case insensitive.
To correct change line 171 from "if strfind(location, 'south')," to "if strfind(lower(location), 'south'),"
Thanks for your work. But there are some unknown reason make it doesn't work well in Matlab 2017. Location and box setting do not work.
Thank you.
Is there a way to control the horizontal spacing between columns ?
Perfect. Just what I needed thanks.
@Simon Henin
It's a very usefull code,thank you very much.
but I found it doesn't work when i choose 'hist' of bar, why? follow is a example in Matlab 2017a:
y = [2 2 3; 2 5 6; 2 8 9; 2 11 12];
h=bar(y,'hist')
columnlegend(3,cellstr(num2str([1:3]')),'location','eastoutside');
Good code. To make the legend more condensed I reduce the line length and text space using a somewhat crude method:
Line 98: line_width = (xdata(2)-xdata(1))*rescale/L_R; % rescaled linewidth to match original
Line 99: spacer = xdata(1)*rescale/L_R;
% reduce the line and spacer by L_R=2.7
%Reduce space between columns St_R=1.6
Line 45: set(object_h(linenum), 'xdata', [col/numcolumns/St_R+spacer col/numcolumns/St_R+spacer+line_width]);
set(object_h(linenum+1), 'ydata', [height-(position-1)*sheight height-(position-1)*sheight]);
set(object_h(linenum+1), 'xdata', [col/numcolumns/St_R+spacer*3.5 col/numcolumns/St_R+spacer*3.5]);
set(object_h(labelnum), 'position', [col/numcolumns/St_R+spacer*2+line_width height-(position-1)*sheight]);
%Changed St_R and L_R to suit
Hello,
I am trying the function R2015b. I get the following error:
Error using matlab.graphics.primitive.Group/get
There is no vertices property on the Group class.
Error in columnlegend (line 97)
vertices_1 = get(child, 'vertices');
Is there a solution to this issue?
It's a great program, but how to change the front size?
Hi, works great but is it possible to set the number of rows per column? As in, if I have 13 entries and want 3 columns of 4,4, and 5 rows?
Thanks a lot..this one is easy to use.....
ONE PROBLEM, When saving figure using savefig('filename.fig'), the columns are merging into one ! Looking for solution....
Thank you for this great function. I want to know that is there anyway to change the background color of the legend. Thanks.
Hi Simon, thank you very much for the function. I am experiencing one issue, though. If I change the font size using the method below, it will be reset to the default when I try to move the objects in the figure manually. Do you have any ideas how to deal with that? Thanks.
@Roger
Take a look at conversation with Qasim from June 5th. That should solve your problem.
I like this it works really well apart from I can't set the size of the legend font. Is there anyway to do this? Or add it into the code as a argument?
@Qasim
Actually got inspired to quickly add an extra option to the function, namely a "padding" option which adds additional space (in normalized units e.g. 1 = 100% additional padding) between legend entries. So something like:
r = rand(10,5);
plot(r);
[h,objs]=columnlegend(2, {'h_1', 'h_2', 'h_3', 'h_4', 'h_5'}, 'location', 'southeast', 'padding', 1);
Let me know if that helps!
@Simon,
Thanks for the fast reply. I got the same effect by adding the fontname attribute (\{times new roman}) to the string cell that I feed to columnlegend. Also changed the font to a larger number which causes the legend lines to overlap if placed southeast or southwest. Was wondering how i could add more space between the different legend rows. If i can solve that then everything works perfectly. Thanks for the function.
@Qasim
Sure. You just need to format the returned text objects:
plot(r);
[h,objs]=columnlegend(2, {'h_1', 'h_2', 'h_3', 'h_4', 'h_5'}, 'location', 'northeastoutside');
drawnow; % make sure everything is finished rendering
set(findall(objs, 'type', 'text'), 'fontsize', 18, 'interpreter', 'tex')
Is there any way to change interpreter to latex? also font size for the legend entries?
Hi, Unfortunately it's not working here. That's the error message I get:
Attempted to access vertices_1(2,2); index out of bounds because
size(vertices_1)=[1,2].
Error in ==> columnlegend at 92
sheight = vertices_1(2,2)-vertices_1(1,2);
Error in ==> Comparando_Massas_m at 39
columnlegend(6,legend_str,'NorthEast');
This is a great function but unfortunately it does not support patches:
>> h=patch('FaceColor',[1 0 0],'EdgeColor','black');
>> columnlegend(h,1,'TEST', 'location', 'northeast','boxoff');
Is this something that could be added in the future?
Thanks a lot!
@Kevin Delaney
This seems to be a bug in R2016b, which I cannot seem to resolve. It does not happen in previous releases (R2016a) or in the latest (R2017a) Release. My suggestion is to upgrade or downgrade if you would like to use this function.
This is a great function; I use it all the time and it makes plots look more professional.
But I'm getting errors with R2016b if I resize axes containing a columnlegend:
Struct contents reference from a non-struct array object.
Error in matlab.graphics.illustration.Legend/doMethod>doUpdateCompatible
Error in matlab.graphics.illustration.Legend/doMethod
Error in matlab.graphics.illustration.Legend/doUpdate
Anyone have a workaround? I've submitted a bug report to MathWorks but they say it's "third-party software" and therefore not their problem.
Hi,
My legend entries have multiple lines (newline characters within the string), but using this only allocates one line per entry. Is there a way to change this?
Thanks!
@yangyang
You can change the font size and type by using this easy code:
leg_str={'\fontname{Times New Roman}\fontsize{13} data 1','\fontname{Times New Roman}\fontsize{13} data2')
h = columnlegend(2,leg_str);
Hi Simon,
Many thanks for your quick reply. It solves my issue.
@A. The "Best" locations are not yet implemented in this version. However, you can use any of the traditional outside locations (e.g. Southoutside, Northeastoutside).
Is it possible to place the legend outside of the plot using columnlegend? An example
figure;
subplot(211) % Reference plot
plot(rand(100,2));
legend('Test1', 'Test2','location','bestoutside');
subplot(212); % Test plot
plot(rand(100,2));
columnlegend(2, {'Test1', 'Test2'},'location','bestoutside');
@Sawoth
Good catch. I will add this as an option in a future update. For now here is a simple work around:
figure; plot(rand(100,2)); [~,h]=columnlegend(2, {'test_1', 'test_2'});
drawnow;
set(findall(h,'type', 'text'), 'interpreter', 'none'); % change the interpreter on all text objects with the legend object
Hi Simon,
Congrats on this awesome function, however the Interpreter cannot be switched off which leads to annoying legend display when using underscores.
Thanks!
@Claire
The function does not work with bar graphs at the moment.
Hi,
I keep getting the following error :
Error using matlab.graphics.primitive.Group/get
There is no xdata property on the Group class.
Error in columnlegend (line 72)
xdata = get(object_h(numlines+1), 'xdata')
I am trying to split a bar chart legend into columns. Does anyone have any advice? Thanks.
@Chocolateee
Updated 'southoutside' location option
Hi Simon, I encountered a small problem when specifying the legend location to be "southoutside": the legends are too close to the x axis and hence overlap with the x ticks in date format. I don't have this problem when using the "legend" command.
@Patrick
Just uploaded a new version with new legend positions, including outside legends.
does not work for outside legends...
Hello,
I have trouble with input argument. I am using MatlabR2012b and I am keep getting the error: Undefined function 'columnlegend' for input arguments of type 'cell'.
Even if I run the example code.I got this error :(, any suggestion anyone?
Hello Mikkel Gryning
Somehow, the code change fontsize back to 9 no matter what number I put in the input.
Hello Mikkel Gryning
Your way doesn't change at all. I am using 2016a
@Daniel
The wat to set fontsize is not working. It changes the size of the box but the fontsize remains the same.
I am using 2016a
@Padraig
you could try something like this:
plot(rand(10,3));
leg_str={'\fontname{WingDings} Text A','Text B','Text C'};
h = columnlegend(3,leg_str);
Obviously, change to a system supported font and apply to all legend entries.
Hi Simon,
Is there any way of setting the FontName? It doesn't seem to work for me:
leg_str={'Text A','Text B','Text C'};
h = columnlegend(3,leg_str);
set(h,'position',[0.15,0.85,0.75,0.1],'FontName','Times New Roman')
Cannot place the legend southoutside
when i save the image as Matlab figure and reopened it, the column format disappears.
Great function. For people that would like to use the 'NorthOutside' location, just add the following code in switch lower(location) (i.e. at line 124):
case {'northoutside'}
set(legend_h, 'position', [pos(1) pos(2)+pos(4) pos(3) 0.05]);
Could you make the legend movable when dragging?
Thank you.
@Christoph
Sure, you could try applying the style after creating the legend. For example:
>> plot(rand(10,3)); h=columnlegend(2, {'1' '2' '3'});
>> set(h,'box', 'on', 'color',[1 0 0])
Hi Simon,
Is there a way to change the background colour of the legend box?
@Daniel, @Mikkel
Thanks for your feedback. I have updated the submission to add this capability and make it compatible with 2015b
As an extension to the comment by Daniel (01/09/2015), this does not work for me in 2015a.
If you as he suggests adds:
case 'fontsize'
fsize = varargin{i+1};
i=i+2;
To the switch loop, but adds,
%create the legend
[legend_h,object_h,plot_h,text_strings] = legend(str);
legendT=findobj(object_h,'Type','Text');
set(legendT,'FontSize',fsize);
It works for me. They must have changed the access pattern in 2015.
Hope that it helps someone :)
Mikkel
Some posts have asked about font size adaptation, and I have also required this. I added a simple workaround (which is a bit bodged, but works for my purposes). You can add a search condition in the first switch loop :
case 'fontsize'
fsize = varargin{i+1};
i=i+2;
Then you can set your fontsize after the basis legend is contructed:
%create the legend
[legend_h,object_h,plot_h,text_strings] = legend(str);
set(legend_h,'FontSize',fsize);
You can call the modified function as normal with the additional fontsize spec:
columnlegend(2,legstr,'location','NorthWest','boxoff','fontsize',20);
Daniel
Hi,
I call this function as columnlegend(2,legendNames,'Location','NorthWest'); However, I got an error as follows.
Error using hg.hggroup/get
The name 'xdata' is not an accessible property for an instance of class 'hggroup'.
Any clue?
Thanks,
Wenwen
Good job for creating the layout.
Some modifications can be made to handle scatter plots, which consist of only one element in legend (linenum = linenum+1;)
I haven't tried with other types of plots
very good!
Very useful and simple to use.
This works out great! The only thing I would like to change is, that the legend can also be located outside the diagram (e.g. 'southwestoutside')
The only possible values at the moment are: 'NorthWest', 'NorthEast', 'SouthEast', 'SouthWest'
Could somebody help me, at which point I would have to adapt the code?
Dear reader,
I tried to plot the exact code as you wrote it but get the error: Undefined function 'columnlegend' for input arguments of type 'cell'.
Error in test (line 9)
columnlegend(3, legend_str, 'Location', 'NorthWest', 'boxon');
Does anyone have a suggestion what it might be?
Thanks!
This is a great tool for relatively simple needs, but I found immediately that I can't do much additional legend customization. Just doing
set(lh,'fontsize',8) caused my legend to revert to a single column. Could you include more input options or perhaps make the legend in a way that changing other properties won't affect the layout?
That's great! Thank you very much.
I wish it also support 'Best' location like the legend of Matlab.
It works very fine with me, I highly recommend to use export_fig to print the plots. I think that it will be a nice improvement if we can pick a 'North' location for example, 'cause if you need to put in the middle of the figure you must move the legend with get 'Position' and set 'Position'. Best Regards Simon.
@Aslak Grinsted
I you want to give it a vector of handles like you can do in the legend function, its a small change in columnlegend.m
first give it a extra input, e.g. 'hdl' in line 1:
function legend_h,object_h,plot_h,text_strings] = columnlegend(numcolumns, hdl, str, varargin)
and then change line 49 as well to:
[legend_h,object_h,plot_h,text_strings] = legend(hdl,str);
Hey there,
I revisited this function today after writing a script to make some custom bar graphs. Anyways, I tried running this function to make a 2-column legend, but hit an error. I then ran the simply code you provided above, and hit the same error, which is:
Error using hg.hggroup/get
The name 'xdata' is not an accessible property for an instance of class 'hggroup'.
Error in columnlegend (line 61)
xdata = get(object_h(numlines+1), 'xdata')
I may try fiddling some more tomorrow, but this is only a matter of convenience to make the plot prettier, so if there isn't a simple fix I'm missing no worries about responding.
Thanks!
@Pavlov
As you know, this error is a general MATLAB error when it cannot find the function in its path. The reason why it is 'double' is because the first argument of columnlegend is a figure handle cast as a double.
Best,
Simon
I know from trial-and-error that this error just has to do with pointing to the right folder in matlab, but it just isn't clear exactly what this has to do with the double format. I know double has to do with exactly how the info is being saved or read by matlab, but it's still mysterious to me exactly what double is or at least when/why this format is needed.
Actually, this is my error:
"Undefined function 'columnlegend' for input arguments of type 'double'. :
It's not clear to me what makes the input argument('leg_str') a double type of variable. I tried num2str(leg_str) as well.
New to matlab here, but this function will be very convenient for me to use. I get the following error whether I copy/past your code here, or call the function using my own str:
Undefined function 'columnlegend' for input arguments of type 'cell'.
I forgot, you ll have to go also to the print function, highlight print and ctrl+D and comment line 293
% pj = restore( pj, h );
For those who has a problem with printing when changing the legend, I find a solution.
insert this after legend is created inside the function columnlegend
pt = getprinttemplate(gcf);
cd('C:\Program Files\MATLAB\R2012a\toolbox\matlab\graphics\private')
ptpreparehg(pt,gcf);
cd(link0)
and copy past the legend command
lin0 is your main directory.
Also you may want to run Matlab as Administrator.
The raison the legend is modifyind when printing is because print function will set the front weight , name, of your text inside the legend. If this is modify the legend come back to its original position.
try this
set(legend_h1,'FontName', 'Helvetica')
you will see the legend will reset.
I modify the function also such that I create the legend in my script and insert it as a parameter inside the function . I inserted the 3 lines solution between the creation of the plot and my call for columnfunction.
If you have any pb I ll be happy to help
@ Mik
Thanks for your comment. Not included in the documentation is the fact that the function returns the legend's object handles. Therefore, you could alter these properties on your own.
Something like this would do it:
[legend_h,object_h,plot_h,text_strings] = columnlegend(...);
set(legend_h,'box','on', ...
'color','y', ...
'ycolor','m', ...
'xcolor','b', ...
'visible','on');
Hey. Very nice function. Just what i needed.
Is there any way to make it non-transparent? My graphs are making the text somewhat illegible.
I'm getting this error (using Matlab R2013a):
Error using hg.hggroup/get
The name 'xdata' is not an accessible property for an instance of class 'hggroup'.
Error in columnlegend (line 61)
xdata = get(object_h(numlines+1), 'xdata');
Any clues? Thanks!
Hi, very nice part of code! But the columns of legend are put together ones the .eps figure is printed. Do you have any idea how to fix it?
Thanks,
Lukas
very useful
I want to change the fontsize of the legend to 14, is that possible?
The text is to small to see in a document, the way it is.
I found a bug of this program. For example, when you try to change 1_by_2 legends to 2_by_1, this program will not work. Because the numpercolumn is 1, and the col is always -1.
Replace the code
“
if mod(i,numpercolumn)==1,
col = col+1;
end
“
with
“
if numpercolumn>1,
if mod(i,numpercolumn)==1,
col = col+1;
end
else
col=i-1;
end
“
to kill this bug.
The columnlegend hides the box around the legend as it is not possible to force the box to be smaller than the
original height. The work around to display box is to use annotation.
The following code can be added at the very end of "columnlegend" to show the box around legend:
pos = get(legend_h, 'position');
orgHeight =pos(4);
pos(4) = orgHeight/numlines*numpercolumn;
pos(2)=pos(2)+ orgHeight-pos(4);
annotation('rectangle',pos)
Hi Simon,
I mixed line plots and scatter plots, what a pitty.
Anyhow, the function is great.
Thanks.
Javier
@ Javier
Unfortunately, at this time this script only works for line graphs, such as created via the plot command. You were probably trying to use the script on a bar or other non-typical matlab figure object.
Best,
Simon
Hi,
I am having a problem with one of my graphs:
??? Error using ==> get
There is no 'xdata' property in the 'hggroup' class.
Error in ==> columnlegend at 42
xdata = get(object_h(numlines+1), 'xdata');
I dunno the reason. The function works with the example on http://blogs.mathworks.com/pick/2011/02/11/create-multi-column-plot-legends/
Update: The problems probably has nothing to do with subplots (tried it in a simple example). Error message:
??? Index exceeds matrix dimensions.
Error in ==> columnlegend at 77
set(object_h(linenum), 'ydata', [(height-(position-1)*sheight)
(height-(position-1)*sheight)]);
Brilliant, just what I need. Have problems with subplots, though.
@Mathias
Please refer to the full file description. To export to vector graphics files, use an advanced figure export (I recommend export_fig, http://www.mathworks.com/matlabcentral/fileexchange/23629).
not compatible with eps format.
So not useful to generate figures to be included in latex documents....
Nice, useful and compact code! It would be nice if i could give it a list of handles to put in the legend.
Thanks for the comment, this has been fixed.
Nice, but doesn't work if you have used markers.
Genius