function mHist = hist2d ([vY, vX], vYEdge, vXEdge)
2 Dimensional Histogram
Counts number of points in the bins defined by vYEdge, vXEdge.
size(vX) == size(vY) == [n,1]
size(mHist) == [length(vYEdge) -1, length(vXEdge) -1]
mYX = rand(100,2);
vXEdge = linspace(0,1,10);
vYEdge = linspace(0,1,20);
mHist2d = hist2d(mYX,vYEdge,vXEdge);
nXBins = length(vXEdge);
nYBins = length(vYEdge);
vXLabel = 0.5*(vXEdge(1:(nXBins-1))+vXEdge(2:nXBins));
vYLabel = 0.5*(vYEdge(1:(nYBins-1))+vYEdge(2:nYBins));
pcolor(vXLabel, vYLabel,mHist2d); colorbar
Kangwon Lee (2020). 2D Histogram Matrix (https://www.mathworks.com/matlabcentral/fileexchange/1487-2d-histogram-matrix), MATLAB Central File Exchange. Retrieved .
MATLAB provides the function hist3 to generate bivariate (2D) histograms
Very useful but a little buggy.
Depending on you bin sizes you use, the program can crash due to machine rounding errors.
Change lines 25 & 26 in Plot2dHist to read:
vLabelX = linspace(rMinX+0.5*rDeltaX, rMaxX-0.5*rDeltaX, size(mHist2D,2));
vLabelY = linspace(rMinY+0.5*rDeltaY, rMaxY-0.5*rDeltaY, size(mHist2D,1));
Leiguang Wang: You've misunderstood this code. At line 38 vColFound will be an empty matrix if line 36 doesn't find any values within the given x bin. isempty is the correct function to call here. Your preferred code would break if the y bin spanned 0 and only had counts exactly at 0 in that bin.
I do have a small issue though. The handling of values exactly at the bin edges is different in x and y. Line 36 reads:
vColFound = vCol((vRow > rRowLB) & (vRow <= rRowUB));
To match what histc does in y this should really have >= and < rather than > and <=. This is most likely not a problem in the majority of cases.
very fast. but has a little bug.
in line 38
expression: if (~isempty(vColFound))
this is always true, since even (vColFound == 0)
doesn't mean vColFound is empty .
if (abs(vColFound(:))~= 0) is preferable.
the function has a bug that I was unable to locate, it was faster to write my own function; it affects the last row and the first column, (or viceversa)
for instance with this data
x = [
0 0 1 1 0 0.4 0.6 0.6 0 0.4 0.4 0.4 0.6 0.6 1 1];
y = [
0 1 0 1 0.6 0.4 0 0.6 0.4 0 0.6 1 0.4 1 0.4 0.6];
but although size(x,2) = size(y,2) = 16
when checking sum(sum(bin_2D)) one gets 9 !
Lines 12 and 13 (where nEdgeX and nEdgeY are defined) are actually useless and can be omitted.
Hi Kangwon Lee and Iain Strachan
Thank you all:)
If the histogram spacing is regular and assumed to be divided between the minimum and maximum values, then one can use the useful property of the sparse(i,j,vals) command, that it sums the values assigned to repeated indices, to do a 2d histogram very quickly, something like this...
function m = mk2dhist(vals,n)
% function m=mk2dhist(vals,n)
% make a 2 d histogram nxn
vX = vals(:,1);
vY = vals(:,2);
vX = round((n-1)*(vX - min(vX))/(max(vX)-min(vX)))+1;
vY = round((n-1)*(vY - min(vY))/(max(vY)-min(vY)))+1;
m = full(sparse(vX,vY,ones(length(vX),1)));
I can't yet think of a simple way to exploit this for non-evenly spaced histograms though
Workes exactly like I wanted.
Very user friendly.
Works well. It's Short and sweet
IMO one needs to swap lines 27 and 28 if the bins in x and y are not equally spaced. If this is not the case, the version as is gives rotated histograms.
Just what I needed.
Excellent, it did exactly what it said it would. Great for contouring dense scatter fields.
Explicit specification of edges is inconvinient. Why do the vectors have to be passed as a matrix? Plotting of the result often doesnt work. Plot is not a 2d bar chart as expected.
Does exactly what it says on the tin! Easy to use, fast, simple, great.
simple and fast
Exactly what I needed
This is what I wanted. Why MATLAB doesn't have this kind of command, I don't understand.
It does what you'd expect :-)
A surface plot instead of contours would be a useful option. I know - I should add this myself!
Adding a separate plotting function
Inspired: 2-Dimensional Histogram