X-Axis Boxplot Shift
22 views (last 30 days)
Show older comments
Is there a way in matlab to use boxplot or boxchart to shift the boxplot to the side of additional data lines such as a scatter or line plot? I am looking to put my scatter point on x-axis 1 and 2 with the boxplot to the side at x-axis 0.5 and 2.5. Image attached of my data and then of an image I found of someone doing this in R.
0 Comments
Accepted Answer
Voss
on 10 Jun 2024
% random data
N = 100;
x = randn(N,1);
cats = categorical(randi(2,N,1),[1 2],{'None','LF'});
% create the box plot
figure
h = boxplot(x,cats);
% shift box plots to the left by 0.3
set(h,{'XData'},cellfun(@(x)x-0.3,get(h,'XData'),'UniformOutput',false))
% create the scatter plots
hold on
scatter(1,x(cats == 'None'))
scatter(2,x(cats == 'LF'))
% adjust the xlimits
xlim([0 3])
0 Comments
More Answers (1)
Adam Danz
on 10 Jun 2024
Edited: Adam Danz
on 10 Jun 2024
This demo plots the boxchart first and then plots the jittered scatter next to the boxes. This differs from the original request to plot the scatter first and offset the box charts.
rng default
% Prep data
load patients
Gender = categorical(Gender);
Smoker = categorical(Smoker,logical([1 0]),{'Smoker','Nonsmoker'});
groupdata = Gender.*Smoker;
% Create boxchart
fig = figure();
b = boxchart(Diastolic,'GroupByColor',groupdata);
legend('Location','southoutside','orientation','horizontal','NumColumns',4)
ax = ancestor(b(1),'axes');
ax.XTick = [];
ylabel('Diastolic pressure (mmHg)')
set(b, 'MarkerStyle','none')
% Compute x-edges of each box
% Centeres will be computed by averaging x-vertex data of boxes
% BoxWidth is not useful with cat axes so edges must be computed
boxchartparts = vertcat(b.NodeChildren);
isBoxFace = strcmpi(get(vertcat(b.NodeChildren),'Description'), 'Box Face');
boxFaces = boxchartparts(isBoxFace);
drawnow()
[boxLeftEdge, boxRightEdge] = arrayfun(@(h)bounds(h.VertexData(1,:)),boxFaces); % in order of b handles
interBoxInterval = min(boxLeftEdge(2:end) - boxRightEdge(1:end-1)); % assumes >1 box
% For each box, add underlying data via scatter with jittered x values
% Jitter width defined by width between boxes
gap = 0.25*interBoxInterval;
scatWidth = interBoxInterval - 2*gap;
hold on
groupcats = categories(groupdata); % in order of b handles
for i = 1:numel(b)
idx = groupdata == groupcats(i);
yvals = Diastolic(idx);
scatBounds = boxRightEdge(i) + [gap, gap+scatWidth];
xvals = rescale(rand(size(yvals)),scatBounds(1),scatBounds(2));
scatter(xvals,yvals, 70, b(i).BoxEdgeColor, ...
LineWidth = b(i).LineWidth, ...
MarkerFaceColor = b(i).BoxFaceColor, ...
MarkerFaceAlpha = b(i).BoxFaceAlpha);
end
Solution 2: add more categories to the x axis
This demo plots grouped scatter objects on a categorical x axes using categories 1 to n (n=2). It then adds addtional categories to make room for the box charts. Set the interval variable to conrol spacing between boxes and scatter.
% Create data
rng default
data = rand(20,2).*[1.1,.9]+[.2 -.2];
group = [1,2].*ones(height(data),1); % categories are 1:n for n boxes.
% Plot scatter using categorical x values
cats = categorical(group);
s = scatter(cats,data);
% Store original x tick values
ax = ancestor(s(1),'axes');
origTicks = ax.XAxis.TickValues;
% Add more categories to the axes
% This assumes double(categorical(ax.XAxis.Categories))==1:n
ncats = numel(ax.XAxis.Categories);
interval = 1/4; % Space between scatter and boxes.
ax.XAxis.Categories = string(1-interval:interval:ncats+interval);
ax.XAxis.TickValues = origTicks;
% Plot the boxchart at an offset to the scatter
hold on
boxcats = categorical(group - interval);
boxchart(boxcats(:),data(:))
0 Comments
See Also
Categories
Find more on Data Distribution Plots 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!