看完这篇,还有你不会画的热力图吗?

2019-10-22 15:56:01 浏览数 (2)

之前有不少小伙伴在公众号里问怎么绘制热力图,今天就给大家说道说道。热力图(Heat Map),最初的定义是指一个以颜色变化来显示数据的矩阵,逐步演化成为用颜色变化来表征某种数据经过降维处理后的变化情况。热力图在各行各业都有着广泛地应用,比如地图热力图、网页/APP热力图以及业务数据热力图等。

基于以上概念,不难理解,绘制热力图所需要的数据往往是3维或者更高维度的,下面给出三维的两种常见的数据样本格式:

格式一、点型数据,即知道三维空间的若干个数据点(x,y,z),其中z为待表征量:

格式二、网格型数据,网格型数据本质上还是点型数据,只是在样本数据预处理时有细微区别,同样z为待表征量:

清楚了样本数据格式后,以人口密度热力图来说明热力图的制作原理,下图是从腾讯位置大数据(heat.qq.com)上截取截取的北京市朝阳区欢乐谷2019年10月18日17:00的人口密度图。

为了绘制上面一张图,首先要获取腾讯地图使用者的位置(经度x, 纬度y),统计规定时间内在某个位置区域使用腾讯地图的人数,将统计的人数除以位置区域的面积即可得到该区的人口密度z。现在数据点(x,y,z)均已获取,不过数据离散性很大。如果只是单纯地绘制所得到的数据,那将是一个个不同颜色的离散点。为了最大化利用获取的数据,使得更具有宏观参考价值,对获取的数据采用数学处理方法进行数据扩充是很有必要的,扩充之后就能实现全域观察,最后形成了上图。

通过上面的简述,相信小伙伴们对热力图的绘制原理应该有所了解了吧。要在二维空间里绘制三维数据,有没有什么办法呢?答案是肯定的,那就是把第三维用另外一种形式来表征,而颜色就是最合适的候选者,将第三维数据与颜色值一一对应,这样就可以在二维空间完成三维数据的绘制。

下面以第一种样本数据格式来演示热力图的绘制:

代码语言:javascript复制
clc;clear;close all;
% 定义点(x,y,z)
x = randn(50,1);
xmax = max(x);
xmin = min(x);
y = randn(50,1);
ymax = max(y);
ymin = min(y);
z = exp(sin(x.^2))   exp(cos(y.^2));
N = 500; % 每个维度的数据点数
% 网格化x,y二维空间
[X,Y] = meshgrid(linspace(xmin,xmax,N),linspace(ymin,ymax,N));
% 采用插值法扩展数据,可用方法有'linear'(default)|'nearest'|'natural'|'cubic'|'v4'|
Z = griddata(x,y,z,X,Y,'v4');
%% 等高线法
figure('NumberTitle','off','Name','等高线法','Color','w','MenuBar','none','ToolBar','none');
contourf(X,Y,Z,N, 'LineColor','none');
colormap('jet');
colorbar;
axis off;
%% 投影图法
figure('NumberTitle','off','Name','投影图法','Color','w','MenuBar','none','ToolBar','none');
surf(X,Y,Z,'LineStyle','none');
xlim([min(X(:)) max(X(:))]);
ylim([min(Y(:)) max(Y(:))]);
axis off;
colormap('jet');
colorbar;
shading interp;
view(0,90);
%% imagesc法
figure('NumberTitle','off','Name','imagesc法','Color','w','MenuBar','none','ToolBar','none');
% 因为图像坐标和笛卡尔坐标起始位置不一样,需要上下翻转
imagesc(flipud(Z));
colormap('jet');
colorbar;
axis off;
%% pcolor法
figure('NumberTitle','off','Name','pcolor法','Color','w','MenuBar','none','ToolBar','none');
pcolor(X,Y,Z);
colormap('jet');
colorbar;
shading interp;
axis off;

0 人点赞