Given a N x N array I want to generate a heat map that visualizes data in such a way:
Given the source image below I created a sparsely populated N X N array that contained the points listed below. 90 points in a 1000x800 array.
When researching online how to generate such a heatmap I stumbled on using colormap only to get disappointing results.
colormap('hot'); % set colormap
imagesc(points); % draw image and scale colormap to values range
colorbar;
I got rather disappointing results.
What other alternatives do I have to make my image above resemble the top one?
Heat maps are a standard way to plot grouped data. The basic idea of a heat map is that the graph is divided into rectangles or squares, each representing one cell on the data table, one row and one data set. The rectangle or square is color coded according to the value of that cell in the table.
Create a matrix of data. Then create a heatmap of the matrix values. Use custom labels along the x-axis and y-axis by specifying the first two input arguments as the labels you want. Specify the title and axis labels by setting properties of the HeatmapChart object.
There are a few different ways you can convert scattered or sparse matrix data into a heatmap that provides some better visualization of the point density. The examples I'll show here will start with scattered data, so if you already have data in a 2D matrix/histogram you can skip the initial steps...
If your scattered data is rather dense, a simple 2D histogram may be all you need. You can create a grid covering your scattered points (at a resolution of your choosing) and bin your data in the x and y directions using histcounts2
:
% Normally distributed sample points:
x = randn(1, 10000);
y = randn(1, 10000);
% Bin the data:
pts = linspace(-4, 4, 101);
N = histcounts2(y(:), x(:), pts, pts);
% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, N);
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
And here's the resulting plot:
If your scattered data is rather sparse, you can still create a histogram as above, but then filter the result to smooth it out. You could use imdilate
if you have the Image Processing Toolbox, or create a filter matrix and use conv2
. Here's an example of the latter:
% Normally distributed sample points:
x = randn(1, 100);
y = randn(1, 100);
% Bin the data:
pts = linspace(-3, 3, 101);
N = histcounts2(y(:), x(:), pts, pts);
% Create Gaussian filter matrix:
[xG, yG] = meshgrid(-5:5);
sigma = 2.5;
g = exp(-xG.^2./(2.*sigma.^2)-yG.^2./(2.*sigma.^2));
g = g./sum(g(:));
% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, conv2(N, g, 'same'));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
And here's the resulting plot:
Starting with a sparse histogram from above, you could use bwdist
from the Image Processing Toolbox to create a distance transform of the data. This would assign each pixel a value based on its distance from the nearest nonzero pixel.
Alternatively, you could avoid computing the 2D histogram by creating a grid covering your scattered points and computing the minimum distance from each grid point to one of your scattered points using pdist2
from the Statistics Toolbox. Here's an example (using the same sample data as above):
% Generate grid and compute minimum distance:
pts = linspace(-3, 3, 101);
[X, Y] = meshgrid(pts);
D = pdist2([x(:) y(:)], [X(:) Y(:)], 'euclidean', 'Smallest', 1);
% Plot scattered data:
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, reshape(D, size(X)));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
colormap(flip(parula(), 1));
And here's the resulting plot:
You first need to calculate the density of points on a xy grid. Here you are just plotting an "image version" of any scatter plot in matlab. So, before plotting, you need to process the data and obtaining the density map derived from you points. You could use for example the ksdensity function, that will estimate the density of points on a grid base. If this function is not available to you, there is a lot of function on the fileexchage that will do the same thing.
% get the x y coordinates of your points
[y,x] = find(points);
P = [x,y];
% estimate and plot the density
[Est,XY] = ksdensity(P);
imagesc(XY(:,1), XY(:,2),Est);
colormap('hot');
colorbar;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With