Scatter plot with mean for multiple groups

23 views (last 30 days)
Hello,
I'm trying to create a scatter plot looks like this:
I don't know the original name but I found this link : https://www.mathworks.com/matlabcentral/fileexchange/62871-cigarscatterplot?s_tid=srchtitle_scatter%20plot_15 I also attached the code that I used. It's slightly different than the original one (because I have more groups).
This is the part of data. I have 4 ranges and 3 experiments for each drug group. for every range I'm trying to add all 3 experiment for each group in same vertical area and box. eventually, my aim is to create 4 boxes for each range next to each other . (I mean; box = the area whic is seperated with dashlines in the scatterplot) and each box is needed to have 4 groups.
I wrote this command
Control= [0,0,0]
ap= [5, 36, 52]
Drug1 = [1,1,1]
bp = [32, 16, 0]
Drug2 = [2,2,2]
cp = [0, 15, 5]
Drug3 = [3,3,3]
dp= [16, 0.00, 1]
x = [Control, Drug1, Drug2, Drug3]
y= [ap, bp, cp, dp]
[x,y]= Tugce3CigarScatterPlot(x,y)
I could only add 1 range for 4 groups with all 3 experiment and looked like this. 0 is Control, 1 is Drug 1,.... , and ylim is experiment data.
I need to change 0 with Control, 1 with Drug 1,... n the xlim. Also need to add different ranges next to this plot.
I'm not sure if it's multiple questions in one question but I couldn't find any information to create this kind of plot other than the link above. If anyone knows this scatterplot's original name, maybe I can search for it and find more information, otherwise I would be really apreaciated for any suggestions for any steps.
Thank you so much
  2 Comments
Tugce Irem
Tugce Irem on 26 Sep 2022
Thank you for the suggestions. I editted my question. I added example data and "What I want" image which shows the 3 different chart should be all together and seperated with dashed lines, all need to be same sections in terms of ylim 0 to 100, xlim should be control drug1 drug2 drug3 instead 0,1,2,3 and I want to add tittle for each dashed seperated sections.
So far I get only individual sections seperately and each of them has different ylim ( 0 to 100 or 0 to 60), and I couldn't changed xlim names.
I will appreciate with any suggestions.
Thank you

Sign in to comment.

Accepted Answer

dpb
dpb on 27 Sep 2022
Edited: dpb on 28 Sep 2022
fn=websave('MATLAB_exampledata.xlsx','https://www.mathworks.com/matlabcentral/answers/uploaded_files/1136975/MATLAB_exampledata.xlsx');
tData=readtable(fn);
iscat=vartype('cellstr');
tData=convertvars(tData,@iscellstr,'categorical');
tData.Mean=mean(tData{:,vartype('double')},2)
tData = 12×6 table
Group Range percentage percentage_1 percentage_2 Mean _______ _____ __________ ____________ ____________ ______ Control <30 98.276 100 93.103 97.126 Control 30-39 1.7241 0 6.8966 2.8736 Control 40< 0 0 0 0 Drug 1 <30 89.394 87.692 90 89.029 Drug 1 30-39 10.606 12.308 10 10.971 Drug 1 40< 0 0 0 0 Drug 2 <30 61.765 75.61 100 79.125 Drug 2 30-39 36.765 24.39 0 20.385 Drug 2 40< 1.4706 0 0 0.4902 Drug 3 <30 33.962 1.6129 88.043 41.206 Drug 3 30-39 52.83 43.548 11.957 36.112 Drug 3 40< 13.208 54.839 0 22.682
hTL=tiledlayout(1,3);
R=categories(tData.Range);
for i=1:numel(R)
hT(i)=nexttile;
if i==1, posn=hT(i).Position; L=posn(1);B=posn(2);H=posn(4);end % left, bottom, height
ix=(tData.Range==R(i));
hSC=scatter(tData(ix,:), 'Group', {'percentage', 'percentage_1', 'percentage_2'},'filled');
hold on
hL=plot(double(tData.Group(ix)).'+0.5*[-1;1],double(tData.Mean(ix)).'+[-0;0], 'r-');
ylim([0 100]+[-2 2]) % add just a little whitespace
hT(i).XAxisLocation='origin'; % and keep axis at origin
title(R(i))
if i>1, hT(i).YAxis.Visible='off';end
xlabel('')
if i==numel(R)
hLg=legend([hSC(:);hL(1)],'Pct 0','Pct 1','Pct 2','Mean', ...
'Location','eastoutside','Orientation','vertical');
posn=hT(i).Position; W=posn(1)+posn(3)-L; % width overall after adding legend
end
end
hA=annotation('rectangle',[L B W H]);
Would be my starting point with a traditional scatter can't run the cigarScatter on online platform; I'll see if I can find some time to look at it some later...that's most of what you wanted on the axes; it isn't so easy to draw the horizontal line with categorical variables; yline works but goes across the whole axis range so that doesn't help and there's only the one point on a categorical axes at which can plot. One way is to introduce "fake" categories into the variable to introduce more granularity in the axis. Another is to lay another axis on top the the existing that is numeric and plot into it; alternatively, just do as the cigar plot guy did; do it all numerically and the just label the ticks; the tick labels and the ticks are independent properties.
Mayhaps that will give some ideas on approaches...
ADDENDUM: "Stealing" from @Chunru using the table variable names and the new feature (introduced R2022b) of being able to use other than a categorical variable in a categoricalRuler axis, just a few enhancements.
Also to add the overall figure box is not too bad with the annotation function; just have to compute the outer boundaries of the axes from first to last to find the overall coordintes.
To add the dividing lines between is another application of annotation with a line; one needs to add the computation of the x-location between the first two and the last two axes to come up with the position at which to draw it; I've left that as "exercise for student" -- it would follow the idea illustrated above in the computation of the overall width -- one has to find the RH position of the first axis by adding the Left and Width position values and then add halve the distance between that location and the Left postion of the second.
With the advent of being able to use numeric data on categorical axis, all it would take would be to add a little jitter to the x position vector to be able to create the "cigarscater" figure without having to fool with it. I looked at it a little last night but it had so much extra baggage coming along with it to handle all the "what ifs" that it does that I didn't feel like trying to delve into just how it actually worked to try to do anything more with it.
  6 Comments
dpb
dpb on 28 Sep 2022
Hmmm...mayhaps I was/am wrong; I thought one could do so with the more recent changes -- I know it doesn't cost a poster status points if change, though.
On the xlabel position, if you want to move it, then save its handle when creating it and adjust the 'Position' value...it's just a text object with (x,y,z) coordinates (z-->0 for 2D graphs)
hXLab=xlabel('X'); % write a label; save handle
posn=hXLab.Position; % retrieve default position
posn=posn.*[1 1.1 1]; % adjust y position by 10% (will be negative so down)
hXLab.Position=posn; % set new position
On axis location,
hT(i).XAxisLocation='origin' , 'Location','southoutside'; % and keep axis at origin
is mixing metaphors of the legend positon with the axis -- they're entirely different; the axis location is only one of 'origin', 'top', 'bottom'; anything else is unallowble.
It's some other modifications up earlier to be able to put the legend at 'southoutside'; I actually had tried it and decided didn't want to take the time to make the other modifications to do so, so took the easiest way out.
To do that and make it all work out in the end, you'll have to add it first before calculating the location of the bottom axes because adding it causes the axes to all be shrunk to be shorter to make room. That'll mean moving the logic up top inside the loop that computes L, B, H to after the legend is created in order to have the axes final positions.
It's all doable; just a lot of bookkeeping and nits to take care of to create the special effects desired. Welcome to HG2!!! You'll be a whizard here shortly and be complaining like me about stuff that should be simpler than it is...

Sign in to comment.

More Answers (1)

Chunru
Chunru on 27 Sep 2022
x = readtable("https://www.mathworks.com/matlabcentral/answers/uploaded_files/1136975/MATLAB_exampledata.xlsx");
x.Group = categorical(x.Group);
x.Range = categorical(x.Range)
x = 12×5 table
Group Range percentage percentage_1 percentage_2 _______ _____ __________ ____________ ____________ Control <30 98.276 100 93.103 Control 30-39 1.7241 0 6.8966 Control 40< 0 0 0 Drug 1 <30 89.394 87.692 90 Drug 1 30-39 10.606 12.308 10 Drug 1 40< 0 0 0 Drug 2 <30 61.765 75.61 100 Drug 2 30-39 36.765 24.39 0 Drug 2 40< 1.4706 0 0 Drug 3 <30 33.962 1.6129 88.043 Drug 3 30-39 52.83 43.548 11.957 Drug 3 40< 13.208 54.839 0
urange = unique(x.Range);
n = length(urange);
for i=1:n
subplot(1,n,i)
x1 = x(x.Range==urange(i), :);
scatter(x1, 'Group', {'percentage', 'percentage_1', 'percentage_2'});
hold on
plot((double(x1.Group)+[-.5 .5])', (mean(x1{:, 3:5}, 2)+[0 0])', 'r-')
title(urange(i))
end
  4 Comments
dpb
dpb on 28 Sep 2022
@Steven Lord -- (Headslap!) Yeah, thanks! I got myself confused and then couldn't get the wrong idea out of head. Too used to scatter not being vectorized to take an array, I guess.

Sign in to comment.

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!