File Exchange

image thumbnail

raacampbell/sigstar

version 1.76 (76.2 KB) by

Add significance bars and asterisks to various plot types

4.52174
25 Ratings

65 Downloads

Updated

Lines and asterisks indicating significant differences between two groups on a plot are commonly used in the life and social sciences. To my knowledge, no MATLAB function for adding these is openly available. sigstar makes it easy to add lines and significance asterisks joining one or more pairs of groups on bar charts, box plots, and even line plots. The user simply supplies the identities of the two groups and the p-value (which the user has calculated using an appropriate test).
** Usage
Group identity is defined as x-axis locations or, optionally, group names (if the x-axis labels are strings). sigstar converts the supplied p-values to the appropriate number of asterisks and plots these over the lines that link the pair of groups. sigstar attempts to intelligently place lines and asterisks so that they do not overlie existing plot elements. By default, bars with longer horizontal extents are plotted above shorter bars. This is the convention and it looks neater. The user has control over the order in which significance bars are added. Modifying the order provides control over the vertical position of the bars. This is important for obtaining a neat result in a cluttered plot.

** More
See examples in "help sigstar" for details. The handles of the added plot elements are returned by default, providing the user with fine control of the plot's appearance. This is important since it's difficult to provision for all possible usage scenarios (see demo_sigstar). The function should produce publication quality results, but you may need to play with the figure size and asterisk font size.

** NOTE: If you have questions or want support, you will get an answer faster if you create an Issue on GitHub: https://github.com/raacampbell/sigstar **

Comments and Ratings (54)

Kristen Eller

Fantastic function! I can imagine this is exactly what many people are looking for. Unfortunately, it's missing one thing for my purposes that I figured I would comment in case other people needed it as well. I, unfortunately, do not seem to be able to incorporate error bars and significance bars in grouped bar graphs. I think this is something inherent to MATLAB's bar function though that is making it now work properly.

Rob Campbell

Rob Campbell (view profile)

Thomas, can you send me the code that fails to produce the correct outcome? Ideally can you create an issue on Github? These comments make a poor support forum and I don't even get notifications from here (even though they're enabled). The problem is likely at the findMinY sub-function, BTW.

Is there a possibility for using sigstar if the data your plotting is significantly different from zero? I'm working with relative values. This would mean that I only want one input in the sigtar command, which is currently not possible.

Thomas Black

Thank for the great function Rob - I only have one issue with it that I haven't been able to resolve from the comments below, which is that on my bar graph, the function fails to account for the error bars and will frequently plot the significance bars on top of them.

I've tried manually changing the Ydata of the significance bars to shift them up - however the text (stars or n.s.) does not move, and I cannot work out how to change this in accordance. It's possible to move it in the plot editor, but this whole process takes a lot of time. What I would like to do is alter the function to use the Y values of the top of the error bar in order to decide where to plot the significance bar, but despite putting a lot of time into it I cannot work out how the code does this. Could you offer some help?

Thomas Black

Rob Campbell

Rob Campbell (view profile)

Joey, the example image is generated by the function demo_sigstar

Joey Bruns

How can you change the y location of the bar like seen in the first graph of the example posted, and how do you change the length of the downward tick marks like in the second graph in the example?

Rob Campbell

Rob Campbell (view profile)

You can alter the presentation using the handles returned by the function. See: "edit demo_sigstar.m" and "help sigstar"
It's plotting lines for all data pairs where to tell it to do so. Just don't tell it to make those lines and no lines will be produced.

Sharah

Sharah (view profile)

Thanks for the excellent function. I am wondering for example NaN, instead of printing n.s. how can I make it prints nothing and also no line? If I put something larger than 0.05 it will print no star but there will be a line. how to make it not printing a line?

Shengnan Liu

Anthony

Rob Campbell

Rob Campbell (view profile)

@Amanda:
Can you file an issue request on the GitHub page with an example of what does not work. The link to the Issue Tracker is in the top right of this page.

Rob Campbell

Rob Campbell (view profile)

@Or Gadish Can you contact me via my profile page and I'll include your updates. Then I'll put this thing up on GitHub to make it easier for people to contribute.

Evan

Evan (view profile)

Had some issue using with line objects. I replaced findMinY with:

function Y=findMinY_New(x)

oldXLim = get(gca,'XLim');
oldYLim = get(gca,'YLim');

axis tight
set(gca,'xlim',x) %Matlab automatically re-tightens y-axis

yLim = get(gca,'YLim'); %Now have max y value of all elements within range.
Y = max(yLim);

axis normal
set(gca,'XLim',oldXLim,'YLim',oldYLim)

Amanda

Amanda (view profile)

Hi, I cannot to plot it correctly over my bar graphs. All that appears are small vertical dashes and stars above some of the bars...

Can somebody help me please?

Thank you!

Or Gadish

Thank you Rob, this is an EXCELLENT file – thank you so much. I've made an updated version combining others' suggestions below and a few others I had. Please contact me if you'd like the updated version, though I've only tested it with boxplots.

Edits:
1. Added AX as input so that you can choose which axis handle to apply sigstar to.
2. Changed Handle Output to cell array.
3. Added the ability to increase YLim as necessary to make space for the stars/n.s. above the objects.
4. Added increased font size to stars/n.s. as per Wei Chen below.
5. Fixed R2014b and onwards issue with Patch object by adding to the findMinY function as per Joseph O'Doherty below.
if isempty(p)
p = findobj(ax, 'tag', 'Box');"
end

Nicky Klaasen

Murty

Murty (view profile)

Murty

Murty (view profile)

Thank you very much.

Wei Chen

Awesome function, but does anyone know how to change the size of the "*" and "n.s."?

I found it.

Ans: Change the sub function
" H=makeBar(x,y,p,font_size) "

The text size can be changed by modifying H(2) as follow:

H(2)=text(mean(x(:)),mean(y)+myRange(ylim)*offset,stars,...
'HorizontalAlignment','Center',...
'BackGroundColor','none','FontSize',font_size);

where font_size specify the font size you want.

Awesome!! Thanks a lot for sharing!

If you happen to be plotting multiple bar plots to the same axis (to have different colors, for example), make the following changes to findMinY() to make it work.
> xd=p.XData;
becomes
> xd=cell2mat({p.XData});

and
> yd=p.YData;
> yd=cell2mat({p.YData});

To handle boxplots in the new graphics system I added the following in the findMin subfunction:

if isempty(p)
p = findobj(gca, 'tag', 'Box');
end

How can I modulate star bar position? Actually, I want to draw star bar above my error bar

Jan Schupp

awesomeness!

Antoine

Hi Rob,

Thanks a lot for sharing your matlab function.
unfortunately I have been not able to run it on Matlab R2009b.

When I try the first example:
bar([5,2,1.5])
sigstar({[1,2], [1,3]})

I have this error:
??? Error: File: sigstar.m Line: 167 Column: 11
Expression or statement is incorrect--possibly unbalanced (, {, or [.

It's look like the "Groups" input is not correct but I don't understand why.
Do you have any ideas?

Thanks a lot for your help.

Zheng Zhiwei

very nice job! thank you!

Anne Urai

In 2014b, the problem lies in the subfunction Y=findMinY(x). Specifically, p = findobj(gca,'Type','Patch'); returns an empty handle, since Patches are handled differently. For an errorbar sigstar (but haven't tried with bargraphs or lines, so this is not a general solution) I solved the problem by changing 'Patch' into 'Errorbar'.

Rob Campbell

Rob Campbell (view profile)

I will look into this soonish.

Alexander

Does not work in 2014b release, but looks great in a previous version of matlab (2011b for me).

In 2014b I get this error :
Error using plot
Vectors must be the same length.

Error in sigstar>makeBar (line 249)
H(1)=plot(x(:),y,'-k','LineWidth',1.5);

Error in sigstar (line 186)
H(ii,:)=makeBar(xlocs(ii,:),thisY,stats(ii));

Error in demo_sigstar (line 11)
H=sigstar(groups,[0.001,0.05,0.04]);

when I try to run demo_sigstar

ondrej

ondrej (view profile)

Error using plot
Vectors must be the same length.

Error in sigstar>makeBar (line 249)
H(1)=plot(x(:),y,'-k','LineWidth',1.5);

Error in sigstar (line 186)
H(ii,:)=makeBar(xlocs(ii,:),thisY,stats(ii));

Robert

Robert (view profile)

Very nice function, thanks for sharing!

Yes that makes sense. Thanks so much

Rob Campbell

Rob Campbell (view profile)

This is the minimal example:
>> clf
>> bar([1,2;3,4],'grouped')
>> sigstar([1.1,2.1])
>> sigstar([0.9,1.1])

Does that make sense? Each group is centred around an integer. You can also automate this by extracting the x values from the graph. But the above works as a first-pass.

Hi Rob
Great code, thanks. I have a grouped bar chart, and would like to add significance stars between bars within each group. I think similar to Ellen's question.
Could you please advise?

Mahsa

Mahsa (view profile)

I've been trying to change the font size of the asterisk, but I can't find a way. I can easily change the line width. Has anyone done this?

Rob Campbell

Rob Campbell (view profile)

Ellen, I don't really understand your question. Probably the best thing is for you to mail me off-line with an example of what you're trying to do.

Ellen

Ellen (view profile)

This is a really useful script but I am struggling to make the sigstar go within the groups - for example in x1, there are 3 bars, and I want to put sigstars between them as opposed to putting sigstars between x1 and x2. Could someone assist? I see someone already asked but I'm still not sure.

Rob Campbell

Rob Campbell (view profile)

I don't think I understand. This function is just a way of reporting statistical results that you have already calculated. So it's up to you to do your stats appropriately if your groups have different sizes.

Andreas

Very great tool!

Is there an easy way to use "sigstar" for groups of different size, for example 10 and 20 subjects

Rob Campbell

Rob Campbell (view profile)

Look through the examples, it should be clear(ish). You manually choose the x values want and tell it to draw the bar across those positions. This is pretty much the only way of doing it since there's no way for the function to know which locations you want to link. It can't know this because it doesn't know the structure of your data.

Mech Princess

how do I do this if my bar plot has more than one bar per x axis value?

Rob Campbell

Rob Campbell (view profile)

Daniel,

The answer is "sort of." On the one hand, yes, you can significance indicators however you want on a line plot. I think Maria's example and those in the function show how to this. On the other hand, *should* you be doing it? What do you mean by "significance of two lines"? In most cases, if you have data that can be plotted along a line, then you should be doing a regression of some sort and reporting the relevant coefficients in the text. It is easy to over-use the graphical significance indicators. To be honest, I myself have never used the sigstar for anything. :)

Rob

Daniel

Daniel (view profile)

great tool. Is there any chance to check significance of to line plots?

I'd like to check out the significance of to lines at -10:5:10. So above the lines a star or two would represent significance. Is this possible?

Maybe this works very similar to Maria's group comparison solution, but I was not able to modify it the right way...

Seban

Seban (view profile)

Thanks to the creater of the script and to Maria, too.

Jeroen Aeles

Rob Campbell

Rob Campbell (view profile)

Awesome graph! I'm glad the function can cope with this sort of thing.

Maria

Maria (view profile)

Thank you for your quick answer!

I was able to figure out how. Here is my example for within groups and between groups comparisons :

figure
barvalues=rand(3,5);
errorsL=zeros(3,5);
errorsU=ones(3,5)*0.05;
handles.bars=bar(barvalues);
hold on
numgroups=size(barvalues, 1);
numbars=size(barvalues, 2);

for i=1:numbars
x=get(get(handles.bars(i), 'children'), 'xdata');
x=mean(x([1 3],:));
pos_bars(i,:)=x;
handles.errors(i)=errorbar(x,barvalues(:,i), errorsL(:,i), errorsU(:,i), 'k', 'linestyle', 'none', 'linewidth', 1);
end
handles.pos_bars=pos_bars;
comp_wgroups={ [handles.pos_bars(1),handles.pos_bars(2)], ...
[handles.pos_bars(1),handles.pos_bars(3)], ...
[handles.pos_bars(1),handles.pos_bars(4)], ...
[handles.pos_bars(2),handles.pos_bars(3)], ...
[handles.pos_bars(2),handles.pos_bars(4)], ...
[handles.pos_bars(3),handles.pos_bars(4)]};
sigstar(comp_wgroups)

comp_bgroups={ [handles.pos_bars(5),handles.pos_bars(6)], ...
[handles.pos_bars(5),handles.pos_bars(7)], ...
[handles.pos_bars(5),handles.pos_bars(8)]};
sigstar(comp_bgroups)

Rob Campbell

Rob Campbell (view profile)

Sure, here's an example:
>> clf
>> bar(rand(3,5))
>> sigstar([1,2])

I just tested it, it works.

Maria

Maria (view profile)

This function is great, exactly what I was looking for!

But I am still not able to make it work with a grouped bar graph. Can you please provide an example?

Rob Campbell

Rob Campbell (view profile)

Felix, I have submitted an update that should fix the issue with the grouped error bars.

Felix

Felix (view profile)

Unfortunately it doesn't work with grouped bar charts.
It' like to add lines and asteriks between two groups of bars, but it gives the error:
"Undefined function or method 'lt' for input arguments of type 'cell'." in findMinY...
would it be difficult to add this functionality?

Updates

1.76

send people to github

1.76

update description that was stripped when moving to GitHub.

1.75

Fix for >R2014b. Now box plots and line plots work with new versions of MATLAB. Code is neater. A few other small improvements. Add demo code. Move to GitHub.

1.41

typo

1.4

change description

1.4

Bar plot code updated to run on 2014b. Boxplots *don't* work (yet) on 2014b. Sorry for the slow updates, but I personally don't use 2014b because the new graphics engine is clearly not ready yet.

1.3

Update code to no longer call the range function, which is part of the stats toolbox.

1.2

Update to work with grouped error bars.

1.1

Add the ability to label data as being not significantly different. Example 2 in the function's help text shows how to do this.

MATLAB Release
MATLAB 8.6 (R2015b)

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video