How to plot already binned data

10 ビュー (過去 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 Center および File ExchangeData Distribution Plots についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by