boxchart - different box width according to number of data points
Show older comments
Hi,
I am looking for a way to set the width of a boxplot according to the number of datapoints within a boxchart.
See attachet an example how it looks like in R. When I try this in matlab, I get an error, because matlab accepts only scalars and no vectors. I would prefer to do all my statistics with matlab, so this function would be very helpful.
Thank you
Markus
1 Comment
Submit it as an enhancement request.
You could try to make it work with boxchart by use of hold on and plotting each bar invidvidually. This would take some doing to manage to get the positions correct and whether could be managed or not I don't know for sure, but other than drawing one from basic primitives, it's all that comes to mind at present.
Accepted Answer
More Answers (1)
With sufficient perserverence it looks as though should be able to make boxchart work...the doc had an easy example to illustrate the idea...
tbl = readtable('TemperatureData.csv');
tbl.Month = categorical(tbl.Month,monthOrder);
hBxCh=boxchart(tbl.Month(iJan),tbl.TemperatureF(iJan),'GroupByColor',tbl.Year(iJan)) % base boxplot; note are two objects, one for each month
iJan=tbl.Month=="January"; % so, pick only one month
figure
hBxCh=boxchart(tbl.Month(iJan),tbl.TemperatureF(iJan),'GroupByColor',tbl.Year(iJan)) % chart it
hBxCh(1).BoxWidth=0.25; % now can set its width
Although it's bound to be tedious, it looks as though one could manage to arrange the complete data such that one could plot it a variable at a time and thereby to get additional objects that could then have their individual bar widths set.
With the by grouping option, it certainly is a reasonable enhancement request to be able to control the barwidth by group as well.
ERRATUM:
Well, pooh! The supplied data file isn't available on this platform...it's
>> which -all temperaturedata.csv
C:\MLR2021b\examples\graphics\data\TemperatureData.csv
>>
on desktop install...first time I've tried to use a demo example and the data haven't been here...I attached the image of what it looks like here.
4 Comments
markus tripolt
on 25 Aug 2024
That would be the expected result with calling boxchart that way; as documented, if you pass an array, it draws one object of bars by grouping. The example and my perturbation of the example used the grouping by color variable option so each color group was a boxchart object and the granularity was created by only passing the values associated with each group, one at a time in the loop. That was the key step your code above is missing.
D=readtable("Data.csv");
D.Lagen=categorical(D.Lagen);
D.D_Lage=categorical(D.D_Lage);
%head(D);
D05=D(D.D_Lage=="5",:);
[r05 c05]=size(D05);
D10=D(D.D_Lage=="10",:);
[r10 c10]=size(D10);
D15=D(D.D_Lage=="15",:);
[r15 c15]=size(D15);
D20=D(D.D_Lage=="20",:);
[r20 c20]=size(D20);
rows=[r05 r10 r15 r20];
[rows_all c_all]=size(D);
bw=rows/rows_all;
figure
hold on
for i=1:length(rows)
ix=(D.D_Lage==categorical(5*i)); % logical addressing each
bc(i)=boxchart(D.D_Lage(ix),D.ft0(ix),'BoxWidth',bw(i));
end
bc
figure
hold on
for i=1:length(rows)
ix=D.D_Lage==categorical(5*i);
bc(i)=boxchart(D.D_Lage(ix),D.ft0(ix),'BoxWidth',bw(i));
if i>1, bc(i).BoxFaceColor=bc(1).BoxFaceColor; end
end
Note the above made a logical indexing expression for each pass through the loop that is the value of each group in turn; then passed only those values for each call inside the loop. This then, created a new barchart object for each(*) and by using the grouping variable, put them on the x-axis in the right location. The case then also set a color for each bar based on the internal color order; the second sets all to the default color of the first; niceties such as that are obvious extensions.
You note the difference is there are now four objects to mung on, not just the one...but we had to manually create each to do so.
Note also that the generic coding way to deal with the indices would be to make your D05, D10, ... variables an array so could index inside the loop rather than where I calculated them. In this case that was easy, in general, that may be "not so much", so being able to index would be key.
(*) barchart sill created one chart object for each element of the array of handles; it just doeesn't know you're fooling it into only plotting one bar at a time of the whole thing that will eventually mimic what the single call would produce as one object. Fortunately, unlike boxplot, TMW did create it to be able to use hold on and get access to al least most of the properties of interest for such customization; one just has to be able to recognize you can go a little further in how it is called to do something not envisioned by the authors. Again, this would be a most excellent enhancement suggestion/request.
markus tripolt
on 25 Aug 2024
Glad to help; kinda' an interesting challenge of what would appear to be a logical ability already...anyways, the only real wart I see with this is the whisker line is also proportional to the bar width so for the narrower ones it is almost invisible. Unfortunately, the WhiskerLines hidden property is currently still just a placeholder; there is no way to get access to the line handles in order to change their length; one would have to add code to add another line where should be of a given length to create the effect.
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!

