Effacer les filtres
Effacer les filtres

several Boxplots in one window of multiple vectors with various length

20 vues (au cours des 30 derniers jours)
Simona Pernischova
Simona Pernischova le 19 Sep 2019
Modifié(e) : Adam Danz le 23 Sep 2019
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

Réponses (1)

Adam Danz
Adam Danz le 19 Sep 2019
Modifié(e) : Adam Danz le 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!

Translated by