69 views (last 30 days)

Show older comments

Jakob Seifert on 6 May 2021

Commented: RJ on 31 Jul 2021

Accepted Answer: Adam Danz

Hey,

I think this question has been asked before:

How to overlay box plot with distribution histogram in the same graph - MATLAB Answers - MATLAB Central (mathworks.com)

But I could not find any proper solution;

so is there a way to achieve something like this:

I'm looking forward to hear your suggestions :)

##### 1 Comment Show -1 older commentsHide -1 older comments

Show -1 older commentsHide -1 older comments

Sambit Supriya Dash on 6 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1504155

Open in MATLAB Online

Yes it is possible to get boxplot and histogram in one plot,

Example,

x = [1 2 3;4 5 6;7 8 9];

y = [5 4 3; 5 7 9; 1 9 3];

figure(1)

hist(x)

hold on

boxplot(y)

hold off

Hope, it helps.

Sign in to comment.

Sign in to answer this question.

### Accepted Answer

Adam Danz on 7 May 2021

Edited: Adam Danz on 7 May 2021

Open in MATLAB Online

This method uses patch objects to display histograms next to each boxplot. It's based on another answer that displays probability density distributions next to vertical scatter plots.

You only need to replace the x and y data and can copy-paste the rest of the code.

Inputs.

x : 1xn vector defining the x coordinate of n boxplots.

y : mxn matrix of raw data for n boxplots

rng('default') % for reproducibility

x = 0:5:30;

y = (randn(300, numel(x)) + linspace(.5,5,numel(x))) .* linspace(.5,2,numel(x));

Set spacing

binWidth = 0.4; % histogram bin widths

hgapGrp = .05; % horizontal gap between pairs of boxplot/histograms (normalized)

hgap = 0.2; % horizontal gap between boxplot and hist (normalized)

Compute histogram counts & edges

hcounts is an nx2 cell array containing the {counts, edges} for each distribution.

maxCount is the maximum bin count across all distributionts, used to normalize patch heights

hcounts = cell(size(y,2),2);

for i = 1:size(y,2)

[hcounts{i,1}, hcounts{i,2}] = histcounts(y(:,i),'BinWidth',binWidth);

end

maxCount = max([hcounts{:,1}]);

Plot boxplots

fig = figure();

ax = axes(fig);

hold(ax,'on')

xInterval = mean(diff(sort(x))); % x-interval (best if x is at a fixed interval)

normwidth = (1-hgapGrp-hgap)/2;

boxplotWidth = xInterval*normwidth;

boxplot(ax,y,'Positions',x,'Widths',boxplotWidth,'OutlierSize',3,'Labels',compose('%d',x))

Add vertical histograms (patches)

histX0 = x + boxplotWidth/2 + hgap; % histogram base

maxHeight = xInterval*normwidth; % max histogram height

patchHandles = gobjects(1,size(y,2));

for i = 1:size(y,2)

% Normalize heights

height = hcounts{i,1}/maxCount*maxHeight;

% Compute x and y coordinates

xm = [zeros(1,numel(height)); repelem(height,2,1); zeros(2,numel(height))] + histX0(i);

yidx = [0 0 1 1 0]' + (1:numel(height));

ym = hcounts{i,2}(yidx);

% Plot patches

patchHandles(i) = patch(xm(:),ym(:),[0 .75 1],'FaceAlpha',.4);

end

xlim([-2.5, 32.5])

Method 2 with color control

With just a few changes to the code above, you can use boxplotGroup() from the file exchange to set up colors of boxplots and histogram similar to the example in your question.

%% Inputs

rng('default') % for reproducibility

x = 0:5:30;

y = (randn(300, numel(x)) + linspace(.5,5,numel(x))) .* linspace(.5,2,numel(x));

%% Set Spacing

binWidth = 0.4; % histogram bin widths

hgapGrp = .15; % horizontal gap between pairs of boxplot/histograms (normalized)

hgap = 0.06; % horizontal gap between boxplot and hist (normalized)

%% Compute histogram counts & edges

hcounts = cell(size(y,2),2);

for i = 1:size(y,2)

[hcounts{i,1}, hcounts{i,2}] = histcounts(y(:,i),'BinWidth',binWidth);

end

maxCount = max([hcounts{:,1}]);

%% Plot boxplotsGroup()

fig = figure();

ax = axes(fig);

hold(ax,'on')

% Convert y (mxn matrix) to 1xn cell array of mx1 vectors, required by boxplotWidths

yc = mat2cell(y,size(y,1),ones(1,size(y,2)));

xInterval = 1; %x-interval is always 1 with boxplot groups

normwidth = (1-hgapGrp-hgap)/2;

boxplotWidth = xInterval*normwidth;

% Define colors for each boxplot

colors = lines(size(y,2));

% Plot colored boxplots

bph = boxplotGroup(ax,yc,'Widths',boxplotWidth,'OutlierSize',3,'PrimaryLabels',compose('%d',x),'Colors',colors);

set(findobj(bph.boxplotGroup,'-property','LineWidth'), 'LineWidth', 1) % increase line widths

%% Add vertical histograms (patches) with matching colors

xCoordinate = 1:size(y,2); %x-positions is always 1:n with boxplot groups

histX0 = xCoordinate + boxplotWidth/2 + hgap; % histogram base

maxHeight = xInterval*normwidth; % max histogram height

patchHandles = gobjects(1,size(y,2));

for i = 1:size(y,2)

% Normalize heights

height = hcounts{i,1}/maxCount*maxHeight;

% Compute x and y coordinates

xm = [zeros(1,numel(height)); repelem(height,2,1); zeros(2,numel(height))] + histX0(i);

yidx = [0 0 1 1 0]' + (1:numel(height));

ym = hcounts{i,2}(yidx);

% Plot patches

patchHandles(i) = patch(xm(:),ym(:),colors(i,:),'EdgeColor',colors(i,:),'LineWidth',1,'FaceAlpha',.45);

end

##### 5 Comments Show 3 older commentsHide 3 older comments

Show 3 older commentsHide 3 older comments

Jakob Seifert on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1507195

This is insane, thank you very much.

Adam Danz on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1507550

Later I realized my boxplotGroup() function could be used to control the color so I added a 2nd version to my answer. The same could be achieved using boxchart but I haven't worked out those details.

RJ on 31 Jul 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1665962

This seems great and exactly what I was looking for too.

I wondered if there is a way to do this with boxplot y vectors of different lengths or am I missing something? And to add x labels? Thanks!!

Adam Danz on 31 Jul 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1666032

An easy workaround when using vectors of unequal length is to pad the shorter vectors with NaN values so all vecs are the same length and then you can combine them into a matrix. padarray may be helpful.

For labels, use text() function or labelpoints().

RJ on 31 Jul 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1666077

Awesome thanks, I got it working with padcat.

Sign in to comment.

### More Answers (1)

Scott MacKenzie on 6 May 2021

Edited: Scott MacKenzie on 7 May 2021

Open in MATLAB Online

This solution uses tiledlayout and boxchart, but you can adjust to use subplot and boxplot if you are running an older version of MATLAB:

n = 7;

y = randn(100,n);

tiledlayout(1, 2*n);

for i=1:n

nexttile;

boxchart(y(:,i));

set(gca,'visible', 'off', 'ylim', [-4 4]);

nexttile;

histogram(y(:,i), 20, 'orientation', 'horizontal');

set(gca,'visible', 'off', 'ylim', [-4 4]);

end

f = gcf;

f.Color = 'w';

f.Units = 'normalized';

f.Position = [.1 .2 .8 .4];

##### 6 Comments Show 4 older commentsHide 4 older comments

Show 4 older commentsHide 4 older comments

Jakob Seifert on 6 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1504620

Thank you for your answer, but this isn't what I am exactly looking for.

I want the y-axis to be the possible outputs for the boxplot, as well as the histogram. That is, I want the histogram to be rotated by 90° degrees. (look at the picture embedded in my original post)

Scott MacKenzie on 6 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1504650

I just adjusted my answer so the histograms are horizontal. Is that what you are looking for?

Jakob Seifert on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1506775

Yes this looks much better! But as I understand it, you turned off the individual axes. I need two "overall" axes; meaning something like this:

https://www.mathworks.com/help/examples/stats/win64/CreateBoxPlotsForGroupedDataExample_01.png

But this soultions is already pretty good ! thank you

Scott MacKenzie on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1506940

Edited: Scott MacKenzie on 7 May 2021

You're right. My solution creates 14 plots in 14 axes, all of which are made invisible. To get exacly what you want, you'd need to add all the plots to a single axis or add axes to the parent tiledlayout or figure. I don't know if that's possible.

Adam Danz on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1507160

Edited: Adam Danz on 7 May 2021

Open in MATLAB Online

One more step: it's important to set ylim so that the extent of the histograms align with the extent of the boxplots/outliers. For example, in the 5th pair of axes the boxplot does not show any outliers at the top but the histogram extends beyond the upper cap. This is because of a difference in y-limits between the neighboring axes.

Also, the ylim needs to match for all axes so that vertical differenced between columns of data are preserved.

For example, compare these two figures using the exact same data.

n = 7;

y = randn(100,n) .* [1:3:19];

figure()

boxchart(y)

figure()

tiledlayout(1, 2*n);

for i=1:n

nexttile;

boxchart(y(:,i));

set(gca,'visible', 'off');

nexttile;

histogram(y(:,i), 20, 'orientation', 'horizontal');

set(gca,'visible', 'off');

end

f = gcf;

f.Color = 'w';

f.Units = 'normalized';

f.Position = [.1 .2 .8 .4];

Scott MacKenzie on 7 May 2021

#### Direct link to this comment

https://support.mathworks.com/matlabcentral/answers/822795-boxplot-and-histogram-in-one-plot#comment_1507230

Hey, good point. Thanks. I just adjusted my solution to prevent this -- by setting the y-axis limits.

Sign in to comment.

Sign in to answer this question.

### See Also

### Categories

MATLABGraphicsFormatting and Annotation

Find more on **Formatting and Annotation** 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!

**An Error Occurred**

Unable to complete the action because of changes made to the page. Reload the page to see its updated state.

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list

Americas

- América Latina (Español)
- Canada (English)
- United States (English)

Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- Deutsch
- English
- Français

- United Kingdom(English)

Asia Pacific

- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)

Contact your local office