File Exchange

image thumbnail

simonhenin/columnle​gend

version 3.0.0.0 (53.4 KB) by Simon Henin
Creates a legend with a specified number of columns

291 Downloads

Updated 28 Jun 2018

GitHub view license on GitHub

Editor's Note: This file was selected as MATLAB Central Pick of the Week

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

Comments and Ratings (175)

Jonathan

Baolei Wu

@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.

Simon Henin

@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.

Baolei Wu

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.

Simon Henin

@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

GreenPiece

@Simon Henin
I am using Matlab 2016a.

Simon Henin

@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?

GreenPiece

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?

Simon Henin

@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..

Simon Henin

@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

Simon Henin

@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!

Simon Henin

@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!

Simon Henin

@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');

Simon Henin

@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'});

M G

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.

Brian Liu

@Simon, it's really amazing, thanks again!

Brian Liu

Thanks a lot, Simon!

Simon Henin

@Brain

Fixed the bug. You can re-download for functional version.

Brian Liu

By the way, the Matlab version is 2017b.

Thanks

Brian Liu

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{:});

yijun xiang

Auryn_

Thanks!

Simon Henin

@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);

Auryn_

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

Simon Henin

@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

Selim ilhan

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

Simon Henin

@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?

Tiago Dias

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.

Amra Rajuli

Thank you simon

Simon Henin

@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.

Amra Rajuli

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

Namira

Simon Henin

@ 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.

Namira

@ 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?

Simon Henin

@Namira

Your script cannot find the function. Place columnlegend.m somewhere in your MATLAB path (e.g. in same folder as script)

Namira

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

Simon Henin

@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.

Simon Henin

@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

besty456

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

Simon Henin

@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

Simon Henin

@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?

Bolin

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');

ehsan

Guilherme

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

better li

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'),"

Yimao Sun

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.

vprithiv

Is there a way to control the horizontal spacing between columns ?

Perfect. Just what I needed thanks.

frost

@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

tk

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?

Lucky.Bo

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....

pabodha

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.

Simon Henin

@Roger
Take a look at conversation with Qasim from June 5th. That should solve your problem.

Roger Hill

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?

Simon Henin

@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.

Simon Henin

@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');

Mathieu

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!

Simon Henin

@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.

Jacqueline

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!

Ruben

@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);

Tamilpalani

Hi Simon,
Many thanks for your quick reply. It solves my issue.

Simon Henin

@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).

Tamilpalani

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');

DomJung

Simon Henin

@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

Sawoth

Hi Simon,

Congrats on this awesome function, however the Interpreter cannot be switched off which leads to annoying legend display when using underscores.

Thanks!

dhaba india

Simon Henin

@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.

Jonathan

Simon Henin

@Chocolateee

Updated 'southoutside' location option

Friedrich

Chocolateee

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.

Simon Henin

@Patrick
Just uploaded a new version with new legend positions, including outside legends.

does not work for outside legends...

Jan Cerny

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?

yangyang

Hello Mikkel Gryning
Somehow, the code change fontsize back to 9 no matter what number I put in the input.

yangyang

Hello Mikkel Gryning
Your way doesn't change at all. I am using 2016a

yangyang

@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

Simon Henin

@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')

RONG FU

Cannot place the legend southoutside

Erkan Polat

when i save the image as Matlab figure and reopened it, the column format disappears.

Maxime

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]);

Haha

Could you make the legend movable when dragging?
Thank you.

Simon Henin

@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?

Simon Henin

@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

Daniel

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

Wenwen Li

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

Chen

very good!

Alceu Costa

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?

jun jun

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!

Matthew

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?

laoya

That's great! Thank you very much.
I wish it also support 'Best' location like the legend of Matlab.

Jhabriel

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.

Morten

@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);

Pavlov

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!

Simon Henin

@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

Pavlov

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.

Pavlov

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.

Pavlov

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

Simon Henin

@ 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.

Wasim Malik

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

Ligong Han

very useful

Mai

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.

Bill

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.

Bill

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

Simon Henin

@ 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.

Simon Henin

@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.

Simon Henin

Thanks for the comment, this has been fixed.

Amy

Nice, but doesn't work if you have used markers.

Genius

Updates

3.0.0.0

Add more legend locations and better positioning

2.0.0.0

+ Updates for compatibility with 2015a
+ Adds minor improvements as per user suggestions

2.0.0.0

+ Updates for compatibility with 2015a
+ Adds minor improvements as per user suggestions

1.9.0.0

Bug fix

1.7.0.0

Updates/Bug Fixes

1.6.0.0

removed hidden files.

1.5.0.0

Minor bug fix

1.4.0.0

Added functionality when using markers.

1.2.0.0

Add instructions for printing figure with columns

1.1.0.0

Removed Mac OS hidden files from zip file.

MATLAB Release Compatibility
Created with R2008b
Compatible with any release
Platform Compatibility
Windows macOS Linux

Discover Live Editor

Create scripts with code, output, and formatted text in a single executable document.


Learn About Live Editor