How to plot already binned data

조회 수: 19 (최근 30일)
Christian Scalia
Christian Scalia 2021년 1월 28일
댓글: Steven Lord 2021년 1월 28일
Hi all. I made this code that bins my data (Hs and Tp are 2 1x49 matrices). The data as you can see is already binned in bins that are 0.5 "wide". The bins go from 0 to 15.
datay = Hs;
datax= Tp;
edgesx = 0:0.5:15;
edgesy= 0:0.5:15;
valuesx= edgesx(2:end);
valuesy= edgesy(2:end);
Y= discretize (datay,edgesx,valuesx)
X= discretize(datax,edgesy,valuesy)
XY=[Y;X]
-valuesx and values y are used to assign bin values.
-Discretize is used to distribute the Hs and Tp numerical values into the X and Y bins
I would like to make a code that plots Y vs X as square (since the data has equal edges of 0.5).
The number inside the bin is the bin count (i.e. how many entries in that bin)
My final result should look like something on the lines of this (ignore those lines)
I attempted to reach this result by changing this code : https://uk.mathworks.com/matlabcentral/answers/444262-2d-colour-coded-plot-with-already-binned-data (author @Adam Danz ) but it doesn't work as I think I'm not carefully thinking about the dimension of the matrix I want to plot
datay = Hs;
datax= Tp;
edgesx = 0:0.5:15;
edgesy= 0:0.5:15;
valuesx= edgesx(2:end);
valuesy= edgesy(2:end);
Y= discretize (datay,edgesx,valuesx)
X= discretize(datax,edgesy,valuesy)
XY=[Y;X]
%-------------Modified Code------------
xedges = 0:0.5:30; %Axis should go from 0-30
yedges= 0:0.5:30; %Axis should go from 0-30
% Define bottom, left corner (x,y) of each rectangle
[x, y] = meshgrid(xedges(1:end-1),yedges(1:end-1));
% Determine width and height of each rectangle
[w, h] = meshgrid(diff(xedges), diff(yedges)); %Happy with this as the data is already binned in 0.5 wide rectangle
% Normalize c matrix (0:1)
cNorm = (XY - min(XY(:))) / max(XY(:)); % This is what is not working in my case I think
% Create color matrix
% * you can use any color map: https://www.mathworks.com/help/matlab/ref/colormap.html#buc3wsn-1-map
% * if you change the color map here, change it below as well.
% * I'm setting precision here to 4 decimal places
prec = 1e4;
cmat = parula(prec);
% Assign color (row index) to each value in c
cIdx = round(cNorm * prec);
% loop through each rectangle and draw it
figure
axh = axes;
hold(axh, 'on')
for i = 1:numel(cIdx)
% Don't draw rectangle if color value is 0
if cIdx(i) == 0
continue
end
% Draw rectangle
rh = rectangle(axh, 'Position', [x(i), y(i), w(i), h(i)], ...
'FaceColor', cmat(cIdx(i), :), 'EdgeColor', 'k');
end
% Plot cosmetics
grid(axh, 'on')
colormap(axh, 'parula')
colorbar(axh)
caxis([min(XY(:)), max(XY(:))])
%% Sanity check
% Confirm that edges are correct by drawing lines at edges.
% Save and restore axis limits
yl = ylim;
xl = xlim;
plot([xedges;xedges], repmat(ylim', size(xedges)), 'k-') %x bins, vertical lines
plot(repmat(xlim', size(yedges)), [yedges;yedges], 'k-') %y bins, horizontal lines
xlim(xl)
ylim(yl)
  댓글 수: 4
Adam Danz
Adam Danz 2021년 1월 28일
I'm trying to understand the goal conceptually.
From what I understand you have two vectors that are 1x49 and you want to display the data in a 2D grid. How do those two vectors define each value of the grid? For example, let's say the 2D grid (matrix) is called M, how do I map the value of M(i,j) to the two vectors?
Christian Scalia
Christian Scalia 2021년 1월 28일
편집: Christian Scalia 2021년 1월 28일
The data contained in the two vectors are the coordinates of the points I want to plot.
The Hs matrix contains all the y coordinates of each point
The Tp matrix contains all the x coordinates of each point.
The XY matrix contains the x and y coordinate of each point.
For example
Hs= [0.51 0.48 0.48 0.51 0.53 0.58 0.71] %these are just 7 of the 49 entries
Tp= [4.13 3.86 3.78 3.97 3.75 3.89 3.92] % these are just 7 of the 49 entries
Y=[1 0.50 0.50 1 1 1 1] %Hs values are now assigned to the correspoding bin of size 0.5
X=[4.5 4 4 4 4 4 4] %Tp values are now assigned to the correspoding bin of size 0.5
I created a matrix XY beacuse each column of this XY matrix contains the x and y coordinates of 1 point. Therefore 1 datapoint has coordinates x and y contained in each column of the matrix.
The plot (following the size of the bins, 0.5 wide) should have the x axis going from 0 to 5 with increments of 0.5 and the y axis going from 0 to 15 with increments of 0.5

댓글을 달려면 로그인하십시오.

채택된 답변

Adam Danz
Adam Danz 2021년 1월 28일
편집: Adam Danz 2021년 1월 28일
heatmap plots are difficult to customize which is why I recommend using imagesc or histogram2.
This expample below uses histogram2 to produce a plot that looks similar to heatmap plots but doesn't come with the restrictions. See inline comments for details.
% Generate data
rng('default')
Hs = 2.5*randn(1,1000);
Tp = 2.5*randn(1, 1000);
Hs = Hs-min(Hs);
Tp = Tp-min(Tp);
datay = Hs;
datax= Tp;
edgesx = 0:0.5:15;
edgesy= 0:0.5:15;
% Plot histogram2
% * Set DisplayStype to Tile for 2D view
% * Set ShowEmptyBins to Off to hide empty bins
h = histogram2(datax, datay, edgesx, edgesy,...
'DisplayStyle','tile','ShowEmptyBins','off');
colormap('cool') % colormap close to the one in your example
% Plot text labels showing value of 2D bins
% * rounding to closest integer using %.0f
% * Due to small bin size, text labels must be small (6pt font size)
[xTxt, yTxt] = ndgrid(h.XBinEdges(2:end)-h.BinWidth(1)/2, ...
h.YBinEdges(2:end)-h.BinWidth(2)/2);
labels = compose('%.0f', h.Values(h.Values~=0));
xTxt(h.Values==0) = []; % remove 0-bin labels
yTxt(h.Values==0) = []; % remove 0-bin labels
hold on
th = text(xTxt(:), yTxt(:), labels(:),'FontSize',6, ...
'VerticalAlignment', 'Middle', 'HorizontalAlignment','Center');
% Other cosmetics
set(gca, 'xtick', 0:3:15, 'ytick', 0:3:15, ...
'xlim', [0,15], 'ylim', [0,15])
colorbar()
axis equal
% Add text describing labels
text(min(xlim), max(ylim), ...
'*Bin labels are rounded.', 'FontSize', 7, ...
'VerticalAlignment', 'Bottom', 'HorizontalAlignment', 'left')
If you want the image to look even more similar to your example you need to
  • Turn off the bin edge lines
  • Set the face color alpha to something like 50% (0.5) which also requires setting the figure renderer to painters.
% Generate data
rng('default')
Hs = 2.5*randn(1,1000);
Tp = 2.5*randn(1, 1000);
Hs = Hs-min(Hs);
Tp = Tp-min(Tp);
datay = Hs;
datax= Tp;
edgesx = 0:0.5:15;
edgesy= 0:0.5:15;
% Figure renderer must be set to painters if
% your setting the FaceColorAlpha of the
% histogram object, otherwise skip this line.
figure('Renderer','painters')
% Plot histogram2
% * Set DisplayStype to Tile for 2D view
% * Set ShowEmptyBins to Off to hide empty bins
h = histogram2(datax, datay, edgesx, edgesy,...
'DisplayStyle','tile','ShowEmptyBins','off');
colormap('cool') % colormap close to the one in your example
% Set transparency level and turn off bin lines
h.FaceAlpha = .5;
h.LineStyle = 'none';
% Plot text labels showing value of 2D bins
% * rounding to closest integer using %.0f
% * Due to small bin size, text labels must be small (6pt font size)
[xTxt, yTxt] = ndgrid(h.XBinEdges(2:end)-h.BinWidth(1)/2, ...
h.YBinEdges(2:end)-h.BinWidth(2)/2);
labels = compose('%.0f', h.Values(h.Values~=0));
xTxt(h.Values==0) = []; % remove 0-bin labels
yTxt(h.Values==0) = []; % remove 0-bin labels
hold on
th = text(xTxt(:), yTxt(:), labels(:),'FontSize',6, ...
'VerticalAlignment', 'Middle', 'HorizontalAlignment','Center');
% Other cosmetics
set(gca, 'xtick', 0:3:15, 'ytick', 0:3:15, ...
'xlim', [0,15], 'ylim', [0,15])
colorbar()
axis equal
% Add text describing labels
text(min(xlim), max(ylim), ...
'*Bin labels are rounded.', 'FontSize', 7, ...
'VerticalAlignment', 'Bottom', 'HorizontalAlignment', 'left')
  댓글 수: 1
Christian Scalia
Christian Scalia 2021년 1월 28일
@Adam Danz Thank you very much for your help! The fact that you made the script using histogram2 and not heatmpa makes this very very useful as I have more room for customization!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Steven Lord
Steven Lord 2021년 1월 28일
As written, you don't have counts so I would use histogram2 or histcounts2.
% Create sample Hs and Tp matrices
Hs = 15*rand(1, 49);
Tp = 15*rand(1, 49);
datay = Hs;
datax= Tp;
edgesx = 0:0.5:15;
edgesy= 0:0.5:15;
N = histcounts2(datax, datay, edgesx, edgesy);
h = histogram2(datax, datay, edgesx, edgesy);
If you do have the counts in each cell, you could create a heatmap. In this case, if you're not using histogram2 I'm assuming you created N from the example above in some other way.
heatmap(edgesx(1:end-1), edgesy(1:end-1), N)
  댓글 수: 2
Christian Scalia
Christian Scalia 2021년 1월 28일
편집: Christian Scalia 2021년 1월 28일
@Steven LordThe second graph is exaclty what I am looking for! I have 2 small issues that maybe you could help me with?
  • How do I get rid of the empty bins (0 bins). I would like them to disappear so the plot looks like more then one in the figure I attached in the original question
  • Sorry for the dumb question but how do I invert the y axis so that it starts at 0 at the origin
Steven Lord
Steven Lord 2021년 1월 28일
For missing data, store NaN values in the array. There are a few properties associated with how missing data is displayed. The standardizeMissing function may be of use to you in converting the 0's into NaN's.
A = [1 2 3; 4 5 NaN; 7 8 9];
heatmap(A)
figure
heatmap(A, 'MissingDataColor', 'g', 'MissingDataLabel', 'Nothing to see here')
To control the order in which the Y data is displayed, change the YDisplayData property.
h = heatmap(A, 'MissingDataColor', 'w');
h.YDisplayData = flip(h.YDisplayData);
For more information about the properties of a heatmap see this documentation page.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Data Distribution Plots에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by