How to draw the below type of graph in MATLAB?

2 views (last 30 days)
I'm trying to draw a graph of the form below.
But I can't figure out how to draw it.
Attached data here.
I want to hear from the experts.
Thank you.
  3 Comments
Changho LEE
Changho LEE on 10 Sep 2019
Edited: Changho LEE on 10 Sep 2019
The data file is attached here.
Changho LEE
Changho LEE on 11 Sep 2019
The advice made good results.
Thank you.

Sign in to comment.

Accepted Answer

Cris LaPierre
Cris LaPierre on 10 Sep 2019
I didn't worry about importing your data specifically since it appears to be a summary and not the raw data anyway.
% import bar plot data from spreadsheet
opts = detectImportOptions('data.xlsx','Range',[1 1 18 18]);
data = readtable('data.xlsx',opts);
% import line plot data
ave = readmatrix('data.xlsx',"Range","B20");
% Create x vector of 13 months to give room for Dec bar plot
d = datetime(2019,1,1,'Format',"MMM") + calmonths(0:12);
% Plot ave data
plot(d(1:end-1),ave,'k--','LineWidth',1.5)
ylim([0 16])
% Plot 13th month separately to give room for Dec bar plot
hold on
plot(d(end),0)
hold off
% Turn off x-label for Jan 2020
ax = gca;
ax.XTickLabel{13} = "";
% Use position of current plot to determine placement of bar plots
p = get(gca,'position'); % [left bottom width height]
dx = [0 p(3).*days(diff(d))/365]; % width of each month
% Create bin data for bar plots
edges = 1:16;
% plot bar plots by positioning a new axes on top of the current axis
for i = 1:length(d)-1
a = axes('Position',[p(1)+sum(dx(1:i)) p(2) .75*dx(i+1) p(4)]);
b = barh(a,edges,data{:,i+1});
axis off
end
Not perfect, but it should be able to get your started.
ChanghoLee_combinePlots.png
  8 Comments
Cris LaPierre
Cris LaPierre on 11 Sep 2019
Good point. I thought about doing it that way, but went with the summary axis first so that it could set where I needed to place the histograms. Had to hunt for the uistack fxn because of that. I'd never used it before.
Changho LEE
Changho LEE on 11 Sep 2019
This graph is part of my teacher's research in 1975.
His research was so beautiful that I wanted to make it MATLAB and use it for other research.
You made it so perfect and beautiful.
It looks really elegant.
This is a wonderful thing I never thought of.
Thank you very much for creating such a wonderful work of art.
Thank you very much.

Sign in to comment.

More Answers (1)

Adam Danz
Adam Danz on 10 Sep 2019
Edited: Adam Danz on 11 Sep 2019
"Feb" in your excel file has a $ character which needs fixed. If you have many excel sheets, you can fix it from within the code but I assumed it's fixed prior to running this.
The first section loads the data and prepares it for histogram().
The 2nd section defines the plot layout. You can change the margin size etc.
The 3rd section does the plotting and saves each axis handle.
The 4th section cleans up the axes and does all of the cosmetics.
The 5th section overlays an additonal axis at the same scale as the underlying subplots (as dpb suggested) and plots the mean curve.
See comments for details.
data = readtable('data.xlsx');
edgesStr = data{:,1}; %save edges to an array
edges = str2double(cellfun(@(x)regexp(x,'^\d+','match'),edgesStr(1:end-2))); %edges, numeric
data(:,1) = []; %remove edges from data table
data = fillmissing(data,'constant', 0); %replace NaNs with 0
% Determine subplot dimensions (all in normalized units)
nSubplots = size(data,2); %number of subplots needed
LRmargins = [.1,.08]; %left and right figure margins
TBmargins = [.1, .1]; %top and bottom figure margins
subplotWidth = (1-sum(LRmargins))/nSubplots; %width of each subplot
subplotHeight = 1-sum(TBmargins); %height of each subplot
subplotPos = linspace(LRmargins(1),1-LRmargins(2)-subplotWidth, nSubplots); % lateral position of each subplot
% Loop through each subplot, create subplot and plot the data
figure();
binEdges = [edges(:).',edges(end)+1];
sph = gobjects(1,nSubplots); %store subplot handles
for i = 1:nSubplots
sph(i) = axes('Units', 'Normalize', 'Position', [subplotPos(i),TBmargins(1),subplotWidth,subplotHeight]);
histogram(sph(i),'BinEdges', binEdges, 'BinCounts', data{1:17,i},'Orientation','Horizontal');
end
% Clean up
maxBarHeight = max(data{1:17,:},[],'all'); %max bar height
% remove the x axis ticks for all subplots
set(sph,'XTick',[])
% Set the y tick for the left most subplot as the bin lables
set(sph,'YTick', binEdges(1:end-1))
set(sph(2:end), 'YTickLabel',[])
% Make sure all axes have the same ylim
set(sph,'YLim',binEdges([1,end-1]))
% Make sure all axes have same scale
set(sph,'XLim',[0,maxBarHeight])
% Set the month labels along the horizontal, bottom axis
arrayfun(@(x,y)set(x.XLabel,'String',y),sph,data.Properties.VariableNames);
% Label bins
ylabel(sph(1),'Days')
% overlay summary axis
sph2 = axes('Position',[subplotPos(1),TBmargins(1),1-sum(LRmargins),subplotHeight]);
% plot mean curve
plot(data{end,:}, 'r-s','Linewidth',1.5)
% Scale the axis to match the range of subplots
xlim([.5,12.5])
ylim(ylim(sph(1)))
% Turn off axis
axis(sph2, 'off')
190910 235121-Figure 1.png
  9 Comments
Adam Danz
Adam Danz on 11 Sep 2019
Edited: Adam Danz on 11 Sep 2019
Yeah, I would have rather used your last option which should be implemented for tables too.
But instead I used option 4, fillmissing, which is a one-liner that does work with tables.

Sign in to comment.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!