比如说对世界各国的高等教育情况选取指标,用topsis法处理,就可以得到各个国家在教育方面的topsis分数。
那么如何用图直观的表现出来数据结果呢?考虑到美观性,可以采用不重叠的气泡图,气泡(即圆)的半径与topsis得分相关,这样圆的大小就表现了该国家topsis得分的高低。
如下:
matlab实现代码:
首先导入数据:
clc,clear
D=xlsread('排名.xlsx',1,'B2:B16')';%topsis排名前15分数
[~,~,country]=xlsread('排名.xlsx',1,'A2:A16'); %国家名,以备图例
定义气泡半径:
由于topsis得分都在0-1之间,太小了,所以乘以100作为各国气泡半径。
N=length(D); %要画圆的个数
r=D*100; %生成半径
定义图片边长:
假如所有圆都不重叠,占据的最大长度(即图的边长) 不超过圆直径总和
w=2*sum(r); %**区域边长**
产生第一个点,并画圆:
注意第一个圆显然不能让它跑到图外边,可以粗暴地将半径长度定义为圆心坐标。
用[rand,rand,rand]随机色彩。
p=r(1)*ones(1,2); %产生一个随机点
A=p'; %第一点坐标记录进矩阵A中,转置运算
t=0:360;
patch(p(1)+r(1)*cosd(t),p(2)+r(1)*sind(t),[rand,rand,rand])
hold on
产生不重叠气泡的思路:
随机地生成点,比如开始生成第三个圆的圆心坐标,那么判断该点和第1,2个圆心坐标的距离,分别不能小于r3+r1和r3+r2。如果不能达标则继续随机生成点,达标则储存该点坐标,并画随机颜色的圆。
for ii=2:N
p=r(ii)+(w-2*r(ii)-47).*rand(1,2); %产生一个新随机点,rand(1,2)表示产生一行两列(0,1)之间的随机数
while any((A(1,1:ii-1)-p(1)).^2+(A(2,1:ii-1)-p(2)).^2<=(r(1,1:ii-1)+r(ii)).^2) %距离判断不重叠
p=r(ii)+(w-2*r(ii)-47).*rand(1,2);
end
A = [A,p']; %保存新的点到矩阵A
patch(p(1)+r(ii)*cosd(t),p(2)+r(ii)*sind(t),[rand,rand,rand]); %填充一个圆
end
由于想让不重叠的气泡进一步在图中显得比较紧凑,生成坐标时不断调整参数,-47时看起来效果比较好。
@_@虽然还能满足当前目标,但太不智能了,这种图至少还存在两个改进方向:实现每个气泡紧挨着;气泡的颜色自定义一个颜色矩阵,可以的话,让topsis的得分从高到低渐变颜色,然后旁边图上显示出颜色柱。如果以后实现了,回来补,也可能不补(?)
当然,这个图目前可以在tableau软件里实现:
完整代码如下:
clc,clear
D=xlsread('排名.xlsx',1,'B2:B16')';%topsis排名前15分数
[~,~,country]=xlsread('排名.xlsx',1,'A2:A16'); %国家名,以备图例
N=length(D); %要画圆的个数
r=D*100; %生成半径
w=2*sum(r); %**区域边长**
p=r(1)*ones(1,2); %产生一个随机点
A=p'; %第一点坐标记录进矩阵A中,转置运算
t=0:360;
patch(p(1)+r(1)*cosd(t),p(2)+r(1)*sind(t),[rand,rand,rand])
%plot([0 w w 0 0],[0 0 w w 0]); %画区域方框
hold on
for ii=2:N
p=r(ii)+(w-2*r(ii)-47).*rand(1,2); %产生一个新随机点,rand(1,2)表示产生一行两列(0,1)之间的随机数
while any((A(1,1:ii-1)-p(1)).^2+(A(2,1:ii-1)-p(2)).^2<=(r(1,1:ii-1)+r(ii)).^2) %距离判断不重叠
p=r(ii)+(w-2*r(ii)-47).*rand(1,2);
end
A = [A,p']; %保存新的点到矩阵A
patch(p(1)+r(ii)*cosd(t),p(2)+r(ii)*sind(t),[rand,rand,rand]); %填充一个圆
end
legend(country,'Location','EastOutside') %定位图例
title('Top 15 countries with TOPSIS scores in 2020')
hold off
axis equal