Using boxchart, how can I get the boxes to align with my labels?
35 views (last 30 days)
Show older comments
I am using boxchart to plot 8 datasets on the same plot. I'd like them to alternate in color and specify the x-axis labels. I managed to acheive this using a table, but now when I plot the data, the boxes are getting grouped in pairs and the x-axis labels are not aligned properly.
Here is my current output (code below):
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1443772/image.png)
Everything looks good except the labels don't align with the boxes, which are getting grouped in pairs. Does anyone have any ideas on how I can make these labels alignt with the boxes?
roiindx = [1 4 7 8 10]; % pulling specific items from a larger dataset
i=1; % ultimately, this will be in a loop, but I am trying to keep it simple for now
% this is the data, I am pulling 8 ROIs from this data each 5x5pixels
load('extractedROIdata2023.mat')
% simple script to create cell arrays with label data. size = (200x1)
% cats are the 8 different categories
% corrected is really just a logical containing "corrected" & "uncorrected"
[cats, corrected] = generateCategoricalforBoxcharts();
sz = size(right_hduncroi{roiindx(i)});% (5x5 before reshaping)
% reshape selected ROI to be 25x1 before concatenating all into a single
% table which is same size as the cats and corrected label data (200x1)
% right side
rhdunc = double(reshape(right_hduncroi{roiindx(i)},1,sz(1)*sz(2))');
rhdc = double(reshape(right_hdcroi{roiindx(i)},1,sz(1)*sz(2))');
rldunc = double(reshape(right_lduncroi{roiindx(i)},1,sz(1)*sz(2))');
rldc = double(reshape(right_ldcroi{roiindx(i)},1,sz(1)*sz(2))');
% left side
lhdunc = double(reshape(left_hduncroi{roiindx(i)},1,sz(1)*sz(2))');
lhdc = double(reshape(left_hdcroi{roiindx(i)},1,sz(1)*sz(2))');
lldunc = double(reshape(left_lduncroi{roiindx(i)},1,sz(1)*sz(2))');
lldc = double(reshape(left_ldcroi{roiindx(i)},1,sz(1)*sz(2))');
data = [lhdunc; lhdc; lldunc; lldc; rhdunc; rhdc; rldunc; rldc]; % 200x1 double
T = table(cats,data,corrected); % create table with data and labels
dataorder = {'Left HD','Left HD''','Left LD','Left LD''','Right HD','Right HD''','Right LD','Right LD'''};
T.cats = categorical(T.cats,dataorder);
T.corrected = categorical(T.corrected);
boxchart(T.cats,T.data,'GroupByColor',T.corrected)
2 Comments
the cyclist
on 27 Jul 2023
Moved: Voss
on 27 Jul 2023
Can you upload the data file? You can use the paper clip icon in the INSERT section of the toolbar.
Accepted Answer
Voss
on 27 Jul 2023
Edited: Voss
on 27 Jul 2023
All this is the same as what you already have:
roiindx = [1 4 7 8 10]; % pulling specific items from a larger dataset
i=1; % ultimately, this will be in a loop, but I am trying to keep it simple for now
% this is the data, I am pulling 8 ROIs from this data each 5x5pixels
load('extractedROIdata2023.mat')
% simple script to create cell arrays with label data. size = (200x1)
% cats are the 8 different categories
% corrected is really just a logical containing "corrected" & "uncorrected"
[cats, corrected] = generateCategoricalforBoxcharts();
sz = size(right_hduncroi{roiindx(i)});% (5x5 before reshaping)
% reshape selected ROI to be 25x1 before concatenating all into a single
% table which is same size as the cats and corrected label data (200x1)
% right side
rhdunc = double(reshape(right_hduncroi{roiindx(i)},1,sz(1)*sz(2))');
rhdc = double(reshape(right_hdcroi{roiindx(i)},1,sz(1)*sz(2))');
rldunc = double(reshape(right_lduncroi{roiindx(i)},1,sz(1)*sz(2))');
rldc = double(reshape(right_ldcroi{roiindx(i)},1,sz(1)*sz(2))');
% left side
lhdunc = double(reshape(left_hduncroi{roiindx(i)},1,sz(1)*sz(2))');
lhdc = double(reshape(left_hdcroi{roiindx(i)},1,sz(1)*sz(2))');
lldunc = double(reshape(left_lduncroi{roiindx(i)},1,sz(1)*sz(2))');
lldc = double(reshape(left_ldcroi{roiindx(i)},1,sz(1)*sz(2))');
data = [lhdunc; lhdc; lldunc; lldc; rhdunc; rhdc; rldunc; rldc]; % 200x1 double
T = table(cats,data,corrected); % create table with data and labels
dataorder = {'Left HD','Left HD''','Left LD','Left LD''','Right HD','Right HD''','Right LD','Right LD'''};
T.cats = categorical(T.cats,dataorder);
Then, instead of grouping, you can create two separate boxcharts, one for 'corrected' and one not.
idx = strcmp(T.corrected,'corrected');
boxchart(T.cats(idx),T.data(idx));
hold on
boxchart(T.cats(~idx),T.data(~idx));
More Answers (1)
Cris LaPierre
on 27 Jul 2023
Edited: Cris LaPierre
on 27 Jul 2023
This is a result of your data. You are missing data for some of your categories. If you had data in each category, your boxchart should have a blue and orange box centered on each tick. Your figure starts with orange, which means you have no data for T.cats="Left HD" and T.corrected="false".
Here's how the data should look if you have data for each categorical
cats = ["Left HD";"Left HD'";"Left LD";"Left LD'";"Right HD";"Right HD'";"Right LD";"Right LD'"];
cats = repmat(cats,10,1);
data = rand(length(cats),1);
corrected = rand(length(cats),1)>0.5;
dataorder = {'Left HD','Left HD''','Left LD','Left LD''','Right HD','Right HD''','Right LD','Right LD'''};
T = table(cats,data,corrected);
T.cats = categorical(T.cats,dataorder);
T.corrected = categorical(T.corrected);
boxchart(T.cats,T.data,'GroupByColor',T.corrected)
legend
Here's what it looks like if you are missing data in some categories.
T(T.cats=="Left HD" & T.corrected=="false",:)=[];
T(T.cats=="Left HD'" & T.corrected=="true",:)=[];
T(T.cats=="Left LD" & T.corrected=="false",:)=[];
T(T.cats=="Left LD'" & T.corrected=="true",:)=[];
T(T.cats=="Right HD" & T.corrected=="false",:)=[];
T(T.cats=="Right HD'" & T.corrected=="true",:)=[];
T(T.cats=="Right LD" & T.corrected=="false",:)=[];
T(T.cats=="Right LD'" & T.corrected=="true",:)=[];
figure
boxchart(T.cats,T.data,'GroupByColor',T.corrected)
legend
2 Comments
Cris LaPierre
on 28 Jul 2023
Edited: Cris LaPierre
on 28 Jul 2023
In a grouped boxchart, grouped boxes share a tick. So if you have 8 ticks and 2 groups, there should be 16 boxes. If you wanted to use the grouped option here, you would have 4 ticks and 2 groups, with the legend indicating the category.
roiindx = [1 4 7 8 10]; % pulling specific items from a larger dataset
i=1; % ultimately, this will be in a loop, but I am trying to keep it simple for now
% this is the data, I am pulling 8 ROIs from this data each 5x5pixels
load("extractedROIdata2023.mat")
sz = numel(right_hduncroi{roiindx(i)});
grpnames = categorical(["Left HD","Left HD'","Left LD","Left LD'","Right HD","Right HD'","Right LD","Right LD'"]);
catnames = categorical(["Left HD","Left LD","Right HD","Right LD"]);
c = repelem("corrected",sz,1);
unc = repelem("uncorrected",sz,1);
% reshape selected ROI to be 25x1 before concatenating all into a single
% table which is same size as the cats and corrected label data (200x1)
% right side
rhdunc = right_hduncroi{roiindx(i)}(:);
rhdc = right_hdcroi{roiindx(i)}(:);
rldunc = right_lduncroi{roiindx(i)}(:);
rldc = right_ldcroi{roiindx(i)}(:);
% left side
lhdunc = left_hduncroi{roiindx(i)}(:);
lhdc = left_hdcroi{roiindx(i)}(:);
lldunc = left_lduncroi{roiindx(i)}(:);
lldc = left_ldcroi{roiindx(i)}(:);
data = [lhdunc; lhdc; lldunc; lldc; rhdunc; rhdc; rldunc; rldc]; % 200x1 double
corrected = [unc;c;unc;c;unc;c;unc;c];
cats = repelem(catnames([1 1 2 2 3 3 4 4]),sz,1);
cats = cats(:);
grp = repelem(grpnames([1 2 3 4 5 6 7 8]),sz,1);
grp = grp(:);
T = table(cats,grp,data,corrected); % create table with data and labels
T.corrected = categorical(T.corrected)
boxchart(T.cats,T.data,'GroupByColor',T.corrected)
legend('Location','best')
If you want each box to have its own tick and be a different color, the simplest approach is the one Voss shared.
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!