X-Axis Boxplot Shift
28 次查看(过去 30 天)
显示 更早的评论
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 个评论
采纳的回答
Voss
2024-6-10
% 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 个评论
更多回答(1 个)
Adam Danz
2024-6-10
编辑:Adam Danz
2024-6-10
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 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Data Distribution Plots 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!