Search code examples
matlabcolorsheatmapxyz

Generate a heatmap in a set X, Y, Z with Z being the intensity of the color


I have a numerical set X, Y, Z and I would like to reproduce a heatmap with these values. The size of the bin is 20 x 20 and the range of the X and Y axes are from -150 to 150 with Z being the color. Within that bin it should contain the average of the Z values in that range.

In Origin contains this tool to make a heatmap with the average of the values, but I would like to do it in MATLAB. The graph I made in Origin and that I would like to do in MATLAB can be seen in figure 1.

Figure 1

I've tried something like

load xyz.dat 
x = xyz(:,1); 
y = xyz(:,2);
z = xyz(:,3); 
tbl = table(x,y,z); 
h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');

But it printed this warning

Warning: Error updating HeatmapChart. Values in the source table variable 'x' are not grouped into discrete categories. Use the discretize function to group your values.


Solution

  • heatmap expects discrete x and y values. You goal is to bin your x and y's into 20 discrete bins and average the z values for each bin, but x and y themselves are continuous.

    To achieve your goal take the advice of the warning message and use discretize to bin your x and y values.

    % I used the following stand ins for your data:
    % x = rand(540, 1);
    % y = rand(540, 1);
    % z = rand(540, 1);
    
    n_bins = 20; % Number of grid cells
    % If you want the width of the grid cell to be 20, use 
    % n_bins = (max(x) - min(x)) / 20; 
    
    x_discrete = discretize(x, n_bins);
    y_discrete = discretize(y, n_bins);
    tbl = table(x_discrete,y_discrete,z, 'VariableNames', {'x', 'y', 'z'});
    h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');
    

    Heatmap of discretized variables

    Note: Why was this not a problem with the sample data?

    Using your sample data,

    x = [49.8, 14.5, -60.7, -21.6, -10.6];
    y = [45.3, 7.9, 23.9, -58.5, -55.4];
    z = [0.2 , -0.06, -0.35, -0.15, -0.08];
    tbl = table(x',y',z', 'VariableNames', {'x', 'y', 'z'});
    h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');
    

    Does not throw an error because it treats each x and y value as a separate category. heatmap uses a call to categorical to transform the continuous values into categorical values.

    Aside from not really providing the output you want (each point would be its own box instead of averaging grid cells), categorical seems to have a limit in how many categorical values it will create. I wasn't able to find any documentation about exactly what that limit is, but by experimentation, it tops out in the mid 200's. Since your vectors are 540 elements long, you get the warning about using discretize instead.