Horizontal line for each category in a swarmchart with categorical x axis
20 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Jesper Kamp Jensen
il 11 Ott 2023
Commentato: Jesper Kamp Jensen
il 16 Ott 2023
Hi all,
I would like to add a horizontal line in a swarmchart using categorical x axis. I'm using MATLAB2023b.
I'm using swarmchart to plot my data and I get this plot:
I would like to display a horizontal line for the mean value in each bin for each color that only covered that bin on the a-axis.
Like this example from R:
Using yline like give a line across the whole figure.
With line or plot I can get a horizontal line, but that give lines between limits (see green line from N-0 to R-0.15):
x_line = unique(T.x_cat);
figure(ii);
s1 = swarmchart(T.x_cat(T.Pos == "T" & T.Mixing == 'U'), T.y(T.Pos == "T" & T.Mixing == 'U'), '^');
hold on
s2 = swarmchart(T.x_cat(T.Pos == "B" & T.Mixing == 'U'), T.y(T.Pos == "B" & T.Mixing == 'U'), 'v');
hold on
s3 = swarmchart(T.x_cat(T.Pos == "P" & T.Mixing == 'U'), T.y(T.Pos == "P" & T.Mixing == 'U'), '+');
grid minor
xaxis=get(gca,'XAxis');
xaxis.Categories={'N-0' 'R-0.15' 'R-1' 'R-4' 'F-4' 'F-12' 'F-24'};
mean_y1 = mean(T.y(T.Pos == 'T' & T.Mixing == 'U' & T.Storage == "N"));
line([x_line(4); x_line(5)], [mean_y1 ; mean_y1 ]); % Produce same as line below
plot([x_line(4); x_line(5)], [mean_y1 ; mean_y1 ], '--r');
See data here attached.
Thank you for your inputs!
Best,
Jesper
4 Commenti
Risposta accettata
dpb
il 11 Ott 2023
Modificato: dpb
il 11 Ott 2023
load T
T.x_cat=reordercats(T.x_cat,{'N-0','R-0.15','R-1','R-4','F-4','F-12','F-24'});
x_line = unique(T.x_cat);
s1 = swarmchart(double(T.x_cat(T.Pos == "T" & T.Mixing == 'U')), T.y(T.Pos == "T" & T.Mixing == 'U'), '^');
hold on
s2 = swarmchart(double(T.x_cat(T.Pos == "B" & T.Mixing == 'U')), T.y(T.Pos == "B" & T.Mixing == 'U'), 'v');
s3 = swarmchart(double(T.x_cat(T.Pos == "P" & T.Mixing == 'U')), T.y(T.Pos == "P" & T.Mixing == 'U'), '+');
grid, box on
xticks(1:numel(x_line))
xticklabels({'N-0' 'R-0.15' 'R-1' 'R-4' 'F-4' 'F-12' 'F-24'})
will let you plot on numeric x-axis so you can draw lines between categorical locaions, but still look as if were categorical.
The key "trick" is to reorder the x categories into the desired order as you gave for the categorical x axis--then the numeric values are in the order you wish from 1:NumberCategories. You could create them initially that way as well by using the second optional input to the categorical function, optionally also making it an ordinal variable.
I didn't poke around inside the swarmchart properties to see if could extract the range of the x values around each midpoint to adjust the length of the lines to match. As @Cris LaPierre's alternate solution shows, if you stick with only a categorical axis, the options are very limited as a single point is all there is for addressing (as you already knew).
The other alternative I see would be essentially the same thing as above excepting leave the initial axes as categorical, but then overlay a second one to do the lines on as numeric -- that approach has the same issue as your original in having to pick and choose which category is which in sequence that you did manually if you don't turn it into an ordinal array...all in all, it's probably easier as above.
Also, there are similar efficiencies that could be incorporated in the above similar to @Cris LaPierre showed as far as the grouping...one might even manage a one-liner with rowfun or splitapply if reall put one's mind to it! :)
ADDENDUM:
Turns out the X values are the unique values, but there's XJitterWidth property that controls the amount of jitter...so something like
hL1=plot(1+0.5*hSW.XJitterWidth*[-1 1], [mny(1) mny(1)],'r-');
for each mean of y will do the trick -- you might want to make the multiplier just a little larger than 1/2 -- as above it goes to the center of the outside markers, not quite all the way to the edge of the blob..."salt to suit"!
5 Commenti
Cris LaPierre
il 12 Ott 2023
Modificato: Cris LaPierre
il 12 Ott 2023
Just a caution that, based on the data you shared, T_pH.Storage == "N" corresponds to data with x_cat of 'R-0.15' and 'N-0'. Therefore, your averages for m_TN, m_BN and m_PN, which should be for N-0 only, are including values for R-0.15 as well, which appears to be making the average higher than it should be.
It also means that the values for x_cat of 'R-0.15' are not being included in your averages for m_TR, m_BR and m_PR, which will impact those values as well.
Più risposte (1)
Cris LaPierre
il 11 Ott 2023
Modificato: Cris LaPierre
il 11 Ott 2023
Here's one approach. I tried to simplify it, If you ignore the bit about setting up the colors, you may agree.
load T.mat
% define colors (optional)
c1 = [0 0.4470 0.7410];
c2 = [0.8500 0.3250 0.0980];
c3 = [0.9290 0.6940 0.1250];
T.C(T.Pos=="B",:) = repmat(c1,sum(T.Pos=="B"),1);
T.C(T.Pos=="P",:) = repmat(c2,sum(T.Pos=="P"),1);
T.C(T.Pos=="T",:) = repmat(c3,sum(T.Pos=="T"),1);
% Create a new table with just the desired data
T_U = T(T.Mixing=="U",:);
T_U.x_cat = reordercats(T_U.x_cat,{'N-0' 'R-0.15' 'R-1' 'R-4' 'F-4' 'F-12' 'F-24'});
% Create swarmchart
swarmchart(T_U,"x_cat","y",'ColorVariable','C');
grid minor
% calculate means
x_cat_mean = groupsummary(T_U,["x_cat","Pos"],"mean",["y","C"])
% Add horizontal line for each mean (can be hard to see)
hold on
scatter(x_cat_mean.x_cat,x_cat_mean.mean_y,[],x_cat_mean.mean_C,'_','LineWidth',2)
hold off
1 Commento
Vedere anche
Categorie
Scopri di più su Graphics Objects in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!