several Boxplots in one window of multiple vectors with various length

36 views (last 30 days)
Hi all
I could not find an anwser for my question in the Q&A, but it feels like I am not the only one struggeling with this issue...
I would like make a single window plot of 4 boxplots.
Each boxplots is made from 20 vectors, every vector has a different length.
I don't want them in subplots, but in one single window, how do I do that?
This is the code I use that just shows me the last boxplot in the end.
for s=1:2
for n=1:10
p1=boxplot([Flex.E.BP.(ID){n,s}])
p2=boxplot([Abd.E.BP.(ID){n,s}])
p3=boxplot([Dor.E.BP.(ID){n,s}])
p4=boxplot([Dor.W.BP.(ID){n,s}])
end
end

Answers (1)

Adam Danz
Adam Danz on 19 Sep 2019
Edited: Adam Danz on 23 Sep 2019
Unfortunately it's difficult to specify the position of a boxplot along the x axis so when plotting boxplots within a loop, the boxpots are overwritten starting at x=1 on each iteration.
Below I list two ways around that. 1) by using a grouping variable and 2) by using dummy boxplots filled with NaNs so the position along the x axis can be speficied. The grouping variable solution is far superior for reasons discussed below.
Your data consist of 4 datasets, each with 10x2 vectors which will result in 80 boxplots on the same figure. I suggest using 'compact' plot style.
Use a grouping variable
The benefit of this approach is that it's fast and efficient and it keeps the boxplot output organized. The down side is that it requires a little work to combine your data and assign group labels. Follow this example below that uses fake data that matches your data.
% Create fake data; each dataset is a 10x2 cell array,
% each element is a row vector of varying length.
data1 = arrayfun(@(n)randi(10,1,n)+n, randi(25, 10,2)+10,'UniformOutput', false);
data2 = arrayfun(@(n)randi(10,1,n)+n, randi(25, 10,2)+15,'UniformOutput', false);
data3 = arrayfun(@(n)randi(10,1,n)+n, randi(25, 10,2)+5,'UniformOutput', false);
data4 = arrayfun(@(n)randi(10,1,n)+n, randi(25, 10,2)+0,'UniformOutput', false);
% Create grouping variables to group data by boxplot.
% This grouping variable not only identifies what data belongs to each boxplot
% but it also specifies the order of boxplots along the x-axis.
nBoxs = 4 * 10 * 2; %number of boxplots: 4 data sets, each with 10x2 vectors
dataCombined = [data1(:)',data2(:)',data3(:)',data4(:)']; % all data combined
groupID = cellfun(@(x,g)g*ones(size(x)),dataCombined,num2cell(1:nBoxs),'UniformOutput',false);
% Concatenate data and groups into single row vectors
dataVec = [dataCombined{:}];
groupVec = [groupID{:}];
% Plot boxplots
figure()
axh = axes();
p = boxplot(dataVec, groupVec, 'PlotStyle', 'compact');
% Change x tick labels to show [dataset number, column number, and row number]
[colNum, rowNum, datasetNum] = meshgrid(1:2, 1:10, 1:4); %2 columns, 10 rows, 4 datasets
xlabels = strsplit(sprintf('%d %d %2d\n',[datasetNum(:), colNum(:), rowNum(:)].'), '\n');
set(axh, 'FontName', 'Consolas', 'XTick', 1:nBoxs, 'XTickLabel', xlabels(1:end-1))
xtickangle(90)
grid on
% Add vertical reference line to split data by dataset
arrayfun(@(x,i)xline(axh, x,'k-',sprintf('dataset %d',i),'LineWidth',1.5),(0:10*2:10*2*4)+.5,1:5)
% kludge in the x axis label since the ticks will likely cover it
labelAx = axes('Units','Normalize','Position', [.4 .01 .2 .08],'Visible','off');
text(labelAx,.5,.5,'[dataset, column, row]','HorizontalAlignment','center','fontsize', 12,'fontweight','bold')
axes(axh) %return focus to main axes
Using dummy nan-boxplots
You can create columns of NaNs to offset the x position of a boxplot. The benefit of this approach is that you can use a loop and it requires less work to set up. The major down side is that it is incredibly slow and inefficient . Follow this example below that uses the same fake data from above.
% This will be incredibly slow!
nBoxs = 4 * 10 * 2; %number of boxplots: 4 data sets, each with 10x2 vectors
xi = 0; %will specify the x position
axes()
hold on
for s=1:2
for n=1:10
p1=boxplot([nan(numel(data1{n,s}(:)),xi),data1{n,s}(:)],'PlotStyle', 'compact');
p2=boxplot([nan(numel(data2{n,s}(:)),xi+1),data2{n,s}(:)],'PlotStyle', 'compact');
p3=boxplot([nan(numel(data3{n,s}(:)),xi+2),data3{n,s}(:)],'PlotStyle', 'compact');
p4=boxplot([nan(numel(data4{n,s}(:)),xi+3),data4{n,s}(:)],'PlotStyle', 'compact');
xi = xi+4; %4 datasets
end
end

Community Treasure Hunt

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

Start Hunting!