X-Axis Boxplot Shift

26 Ansichten (letzte 30 Tage)
Austin Bollinger
Austin Bollinger am 10 Jun. 2024
Bearbeitet: Adam Danz am 10 Jun. 2024
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.

Akzeptierte Antwort

Voss
Voss am 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])

Weitere Antworten (1)

Adam Danz
Adam Danz am 10 Jun. 2024
Bearbeitet: Adam Danz am 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(:))

Kategorien

Mehr zu Data Distribution Plots finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by