How to draw the below type of graph in MATLAB?
Mostrar comentarios más antiguos
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 comentarios
dpb
el 10 de Sept. de 2019
Nice plot design -- unfortunately, MATLAB doesn't have builtin solution. Best idea I have otomh would be to create 12 axes for each independent month and plot with barh() then add yet another overall to plot the overall monthly average.
How about attaching a .mat file with the data so folks can play around with it instead of having to create their own? Might get a few takers-on for the challenge...
Changho LEE
el 10 de Sept. de 2019
Editada: Changho LEE
el 10 de Sept. de 2019
Changho LEE
el 11 de Sept. de 2019
Respuesta aceptada
Más respuestas (1)
"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')

9 comentarios
Adam Danz
el 10 de Sept. de 2019
Each subplot has an x axis limit from [0, maxBarHeight] in case you need to interpret the 'height' of each bar.
dpb
el 10 de Sept. de 2019
Looks just pretty good, Adam. I see you used histogram which can't handle categorical data as I was thinking to use with barh. But, it will take datetime; would that save some labeling machinations to use actual months, maybe? Now I've closed the doc, not sure if takes a duration or not...just a "for curious".
Thanks dpb,
Histogram can handle categorical data. https://www.mathworks.com/help/matlab/ref/matlab.graphics.chart.primitive.histogram.html#buhzm_z-1-C
When binCounts is specified, doesn't histogram() act as a bar chart?
I only used the months in the xlabel() for the subplots so I just pulled them from the headers in the excel file. No need for datetime or duration inputs to histogram.
Cris LaPierre
el 11 de Sept. de 2019
Hey Adam. I'm just noticing your histograms only contain data between 3 and 7. I thought maybe you'd only loaded the first few rows of data, but it doesn't appear to be the case. Was that intentional?
Changho LEE
el 11 de Sept. de 2019
I was incorrectly indexing a table using row and column indices. This resulted in eliminating some of the data.
% Replaced this
[nanRow, nanCol] = find(isnan(data{:,:})); %find NaNs in data
data{nanRow,nanCol} = 0; % replace NaNs with 0 so histrogram() doesn't throw error
% with this
data = fillmissing(data,'constant', 0); %replace NaNs with 0
Cris LaPierre
el 11 de Sept. de 2019
I see what it is. It's this line of code:
data{nanRow,nanCol} = 0;
This is interpreted as 'access the specified rows for each listed column/variable'. Rows 3-7 are the only rows that never have a NaN, so are never specified in nanRow and therefore don't get changed to 0.
You get the same result doing this:
data{unique(nanRow),unique(nanCol)}=0
or for that matter,
data{unique(nanRow),:}=0
For what it's worth, this wouldn't work for an array either. You can read more here. You would need to use linear indexing instead, which is not supported for tables.
There are a bunch of ways around this. Here are some options:
1. Use a for loop to change NaN to 0 for each NaN
for i = 1:length(nanRow)
data{nanRow(i),nanCol(i)} = 0 % replace NaNs with 0 so histrogram() doesn't throw error
end
2. Chanage NaN to 0 for each variable
for i = 1:width(data)
data{isnan(data{:,i}),i} = 0 % replace NaNs with 0 so histrogram() doesn't throw error
end
3. Extract to an array, use linear indexing, then assign back to table.
d=data{:,:};
d(isnan(d(:)))=0;
data{:,:}=d
Cris LaPierre
el 11 de Sept. de 2019
Ah, much better :)
Categorías
Más información sobre Creating, Deleting, and Querying Graphics Objects en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




