How to create variability charts?

I'm trying to find a way to recreate JMP-style variability charts using MATLAB.
I've tried looking through the Stats Toolbox and the File Exchange, and can't find anything that would do the trick. Anyone have an idea?
Thanks!

3 Comments

How important is the formatting detail? A boxplot will do the job, but look quite different. Which details of the appearance are important to you?
Matt, the critical part is how it understands the hierarchical nature of the groups (in the example, note how oil amt is a subset of batch size, which is a subset of popcorn type), and also how it includes that understanding in the layout of the X axis labeling. The end users are accustomed to this chart layout, and expect to see the same look.
If you know how the 'understanding is included' in that chart, you can use that information and create a boxplot. There is nothing this specialized that is offered in the statistics toolbox. You could put in a ticket with the mathworks as a suggested enhancement along with your usecase.

Sign in to comment.

 Accepted Answer

Matt Tearle
Matt Tearle on 1 Feb 2013
Edited: Matt Tearle on 22 Mar 2013
EDIT: file added to MATLAB File Exchange. Share and enjoy!
Based on your comment above, boxplot with nominal grouping variables will do it:
x = randn(400,1);
y1 = nominal(round(rand(400,1)),{'little','lots'});
y2 = nominal(round(rand(400,1)),{'large','small'});
y3 = nominal(round(rand(400,1)),{'gourmet','plain'});
boxplot(x,[y1,y2,y3])
Hopefully this is basically how your data is already arranged. x contains all 400 observations of the response variable. y1, y2, and y3 are nominal arrays that record each observation's status for the three categories.
The boxplot labeling doesn't emphasize the hierarchy, but the results are correct.
EDIT TO ADD Oops, I got the grouping variables backward. Anyway, this is getting close to what you posted:
boxplot(x,[y3,y2,y1],...
'plotstyle','compact','labelorientation','horizontal',...
'factorseparator',[1,2])
The only problem is that the vertical arrangement of the group labels is backwards, for showing the hierarchy. This can be hacked, though, if you need:
h = findobj(get(gca,'children'),'type','text');
tl = get(h,'position');
tl = cat(1,tl{:});
tl(:,2) = flipud(tl(:,2));
for k = 1:length(h)
set(h(k),'position',tl(k,:))
end
EDIT TO ADD (2): Not pretty, but here's a function that does a reasonable job of approximating the graphic:
function variabilityplot(x,y)
n = size(y,2);
numgrps = zeros(1,n);
for k = 1:n
numgrps(k) = numel(unique(y(:,k)));
end
numgrps = cumprod(numgrps);
N = numgrps(n);
y = fliplr(y);
boxplot(x,y,...
'plotstyle','compact','labelorientation','horizontal',...
'factorseparator',1:n);
hbxplt = get(gca,'children');
hall = get(hbxplt,'children');
halltype = get(hall,'type');
hsepln = hall(end-n+1:end);
htxt = hall(strcmpi('text',halltype));
set(htxt,'units','data')
txtpos = get(htxt,'position');
txtpos = cat(1,txtpos{:});
txtpos(:,2) = flipud(txtpos(:,2));
x = reshape(txtpos(:,1),N,n);
for k = 2:n
m = numgrps(k-1);
for j = 1:N
ii = floor((j-1)/m);
i1 = 1 + m*ii;
i2 = m*(1+ii);
x(j,k) = mean(x(i1:i2,1));
end
end
txtpos(:,1) = x(:);
for k = 1:length(htxt)
set(htxt(k),'position',txtpos(k,:))
end
tlcol = 0.5*[1,1,1];
txtpos = get(htxt,'extent');
txtpos = cat(1,txtpos{:});
xl = xlim;
yl = ylim;
y1 = min(yl);
y2 = min(txtpos(:,2));
y = linspace(y1,y2,n+1);
for k = 2:(n+1)
line(xl,[y(k),y(k)],'parent',gca,'clipping','off','color',tlcol)
end
line(xl(1)*[1,1],[y1,y2],'parent',gca,'clipping','off','color',tlcol)
line(xl(2)*[1,1],[y1,y2],'parent',gca,'clipping','off','color',tlcol)
for j = 1:n
newy = get(hsepln(j),'YData');
newy(newy==yl(2)) = y(j+1);
line(get(hsepln(j),'XData'),newy,'parent',gca,'clipping','off','color',tlcol)
end
delete(hsepln(1))
Trying it out:
x = randn(400,1);
y1 = nominal(randi(2,400,1),{'little','lots'});
y2 = nominal(randi(3,400,1),{'large','medium','small'});
y3 = nominal(randi(2,400,1),{'gourmet','plain','aardvark','potato'},[1,2,3,4]);
y = [y1,y2,y3];
variabilityplot(x,y)
If you think it's useful, I'll clean it up a bit and put it on the File Exchange soon.

8 Comments

Thanks Matt, I don't have access to the Stats Toolbox at the moment to check it out, but I think you've given me some great pointers. I'll test it out next week and get back to you if I have more questions :)
Matt, any thoughts on how I can re-create the look of the boxes around the axis labels as seen in that JMP plot? I tried to enable the EdgeColor of the text objects, and then increase the Margin, but I'd need to be able to specify a separate X an Y margin for this to work...
hi,i tested that code above, it gives an error at grp2inx :
x = randn(400,1);
y1 = nominal(round(rand(400,1)),{'little','lots'});
y2 = nominal(round(rand(400,1)),{'large','small'});
y3 = nominal(round(rand(400,1)),{'gourmet','plain'});
boxplot(x,[y1,y2,y3])
??? Error using ==> grp2idx at 20
Grouping variable must be a vector or a character array
Can you explain the source of this error ? thanks
@Eric: I've added a function that recreates the layout of the labels. It's messy and involves arseing about in Handle Graphics. So making a custom function and calling that might be the best solution. Feel free to copy and use the function I made. Do you think it's worth adding to the FileEx?
@Youssef: that's an odd error. What version are you using? What do you get if you do which grp2idx and help grp2idx? When I get the help, it says explicitly [G,GN] = grp2idx(S) creates an index vector G from the grouping variable S. S can be a categorical, numeric [etc.]
Hey Matt, thanks so much for giving it a shot! I'll take a look at it - I think it definitely merits being a FileEx item if it works OK :) Thanks again!
Matt, that second code you posted works great! I think it's definitely worth a FileEx posting. I'd take you out for a beer too, if you were a little closer :) The only thing that it's missing in order to be perfect is being robust to changing the size of the figure, if you're up for a challenge!
@Eric: sorry it took a while, but if you're still interested, I've now added it to the FEx (link is in my answer above). The figure resizing issue is tricky -- in the end I took the easy(ish) way out and just turned that aspect off entirely.
@Matt thanks very much! Somehow I missed seeing your last comment, so my reply is even later :) Best, Eric

Sign in to comment.

More Answers (1)

Shashank Prasanna
Shashank Prasanna on 1 Feb 2013
You can certainly use boxplots: http://www.mathworks.com/help/stats/boxplot.html
But I am not certain there is something that generates a plot that looks exactly like that. You may have to generate a boxplot and add all the labels below them after that.

Community Treasure Hunt

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

Start Hunting!