上一节介绍了点、线、面和文本等基本图形元素的创建,有了基本图形元素后,就可以用它们搭建新的图表。本节结合若干实例进行介绍。
用球面创建三维散点图
MATLAB中可以方便地使用plot3函数和scatter3函数绘制三维点,但美中不足的是,它们绘制的三维点看起来更像二维点,缺少三维效果。MATLAB中可以用sphere函数绘制单元球面,本例使用该函数生成若干单位球面并进行平移、缩放和着色,获得更美观的三维散点图效果。本例实现了简单三维散点图、复合三维散点图、以及基于球面大小和颜色的度量表示。
code.matlab
tiledlayout(2,2);
nexttile
x=rand(20,1)*20; %20组均匀分布的随机数,值介于0-20
y=rand(20,1)*20;
z=rand(20,1)*20;
%用20组数据绘球面表示的三维散点
for i=1:20
[X,Y,Z]=sphere; %单位球面上各节点的坐标
X=X+x(i,1); %平移
Y=Y+y(i,1);
Z=Z+z(i,1);
surface(X,Y,Z,'EdgeColor','none','FaceColor','y') %绘制球面
end
axis([0 20 0 20 0 20])
axis equal
set(gca,'Color',[0.9 0.9 0.9])
xlabel('X')
ylabel('Y')
zlabel('Z')
grid on
box on
view(3)
camlight
title("Simple Plot")
nexttile
x=rand(20,2)*20; %两列随机数
y=rand(20,2)*20;
z=rand(20,2)*20;
c=['g' 'y']; %颜色数组,绿色和黄色
%用两列各组数据绘制两种颜色的球面散点图
for i=1:20
for j=1:2
[X,Y,Z]=sphere;
X=X+x(i,j); %平移
Y=Y+y(i,j);
Z=Z+z(i,j);
surface(X,Y,Z,'EdgeColor','none','FaceColor',c(j)) %绘制球面,两种颜色
end
end
axis([0 20 0 20 0 20])
axis equal
set(gca,'Color',[0.9 0.9 0.9])
xlabel('X')
ylabel('Y')
zlabel('Z')
grid on
box on
view(3)
camlight
title("Complex Plot")
nexttile
x=rand(20,1)*20; %球面位置
y=rand(20,1)*20;
z=rand(20,1)*20;
s=rand(20,1)*2; %定义球面的半径大小
%绘制各球面
for i=1:20
[X,Y,Z]=sphere; %单位球面各节点的坐标
X=s(i,1)*X+x(i,1); %用s缩放,用x,y,z平移
Y=s(i,1)*Y+y(i,1);
Z=s(i,1)*Z+z(i,1);
surface(X,Y,Z,'EdgeColor','none','FaceColor','r') %绘制
end
axis([0 20 0 20 0 20])
axis equal
set(gca,'Color',[0.9 0.9 0.9])
xlabel('X')
ylabel('Y')
zlabel('Z')
grid on
box on
view(3)
camlight
title("Different Size")
nexttile
x=rand(20,1)*20; %定义每个球面的位置
y=rand(20,1)*20;
z=rand(20,1)*20;
cr=rand(20,3); %定义每个球面的颜色
%绘制各球面
for i=1:20
[X,Y,Z]=sphere; %单位球面各节点的坐标
X=X+x(i,1); %平移
Y=Y+y(i,1);
Z=Z+z(i,1);
surface(X,Y,Z,'EdgeColor','none','FaceColor',cr(i,1:3)) %用指定颜色绘制球面
end
axis([0 20 0 20 0 20])
axis equal
set(gca,'Color',[0.9 0.9 0.9])
xlabel('X')
ylabel('Y')
zlabel('Z')
grid on
box on
view(3)
camlight
title("Different Color")
运行代码生成图2-11。图中左上图为简单三维散点图,右上图为颜色区分的复合三维散点图,左下图用一个变量的值定义球面的大小,右下图用一个变量的值定义球面的颜色。
\[\]
图2-11 用球面实现三维散点图
创建三元散点图
三元图经常用来表示三组数据的占比关系,如图2-12所示,3个坐标轴围成一个等边三角形,它们的取值范围都是0到1,即0%到100%。坐标系中任意一点的坐标值,通过过该点绘3个轴的平行线可以读取到,3个坐标值的和应该等于100%。
\[\]
图2-12 三元坐标系
下面的代码绘制三元坐标系。先用fill函数绘制等边三角形区域,然后绘制网格线。注意,网格线的起点和终点需要作直角坐标系到三元坐标系的转换。然后添加刻度标签和坐标轴标签。
code.matlab
%坐标轴和等边三角形绘图区
h=fill([0 1 0.5 0],[0 0 0.866 0],'w','linewidth',2);
%网格线绘制,起点和终点从直角坐标系向三元坐标系转换
d1=cos(pi/3);
d2=sin(pi/3);
l=linspace(0,1,11); %直角坐标系中的值
hold on
for i=2:length(l)-1
%斜边上的点有转换,底边上的点没有转换
plot([l(i)*d1 1-l(i)*d1],[l(i)*d2 l(i)*d2],':k','linewidth',0.25);
plot([l(i) l(i)+(1-l(i))*d1],[0(1-l(i))*d2],':k','linewidth',0.25);
plot([(1-l(i))*d1 1-l(i)],[(1-l(i))*d2 0],':k','linewidth',0.25);
end
axis image
axis off
%绘制刻度标签
for i=1:11
text(l(i),-0.025,num2str(l(i)));
text(1-l(i)*cos(pi/3)+0.025,l(i)*sin(pi/3)+0.025,num2str(l(i)));
text(0.2-l(i)*cos(pi/3)-0.06,sin(pi/3)*(1-l(i)),num2str(l(i)));
end
%绘制坐标轴标签
text(0.5,-0.05,'C1','HorizontalAlignment','center');
text(0.15,sqrt(3)/4+0.05,'C2','HorizontalAlignment','center','Rotation',60);
text(0.85,sqrt(3)/4+0.05,'C3','HorizontalAlignment','center','Rotation',-60);
hold off
下面的代码在三元坐标系上绘制散点图。跟处理网格线的起点和终点一样,需要将散点的坐标从直角坐标系转换到三元坐标系。
code.matlab
%散点数据
load terplot_data.mat
l=length(B);
B(l+1,:)=[1 0 0 6];
B(l+2,:)=[0 1 0 30];
B(l+3,:)=[0 0 1 1];
d=0.29./sqrt(B(:,4));
c1=B(:,1);c2=B(:,2);c3=B(:,3);
… %省略部分代码
%散点坐标转换和绘制
for i=1:length(c1)
x=0.2-c1(i)*cos(pi/3)+c2(i)/2;
y=0.866-c1(i)*sin(pi/3)-c2(i)*cot(pi/6)/2;
plot(x,y,'ob','MarkerSize',4);
end
… %省略部分代码
运行代码生成三元散点图如图2-13所示。
\[\]
图2-13 三元散点图
创建三元色谱图
三元色谱图的绘制,是在三元散点的基础上,用散点数据生成Delaunay三角网,并以插值方式用渐变色绘制Delaunay三角曲面。
下面的代码创建三元色谱图。
code.matlab
%绘图数据
load terplot_data.mat
l=length(B);
B(l+1,:)=[1 0 0 6];
B(l+2,:)=[0 1 0 30];
B(l+3,:)=[0 0 1 1];
d=0.29./sqrt(B(:,4));
c1=B(:,1);c2=B(:,2);c3=B(:,3);
%绘制三元坐标系
h=fill([0 1 0.5 0],[0 0 0.866 0],'w','linewidth',2);
d1=cos(pi/3);
d2=sin(pi/3);
l=linspace(0,1,11);
hold on
axis image
axis off
for i=1:number
text(l(i),-0.025,num2str(l(i)));
text(1-l(i)*cos(pi/3)+0.025,l(i)*sin(pi/3)+0.025,num2str(l(i)));
text(0.2-l(i)*cos(pi/3)-0.06,sin(pi/3)*(1-l(i)),num2str(l(i)));
end
%计算数据点在三元坐标系中的新坐标
x=0.2-c1*cos(pi/3)+c2/2;
y=0.866-c1*sin(pi/3)-c2*cot(pi/6)/2;
%根据散点计算Delaunay三角网关键矩阵
tri=delaunay(x,y);
%用trisurf函数绘制Delaunay三角曲面
trisurf(tri,x,y,d);
%插值着色
shading interp
%在色谱图上绘制网格线
zmax=max(d);
for i=2:length(l)-1
plot3([l(i)*d1 1-l(i)*d1],[l(i)*d2 l(i)*d2],[zmax zmax]*1.1,':k','linewidth',0.25);
plot3([l(i) l(i)+(1-l(i))*d1],[0(1-l(i))*d2],[zmax zmax]*1.1,':k','linewidth',0.25);
plot3([(1-l(i))*d1 1-l(i)],[(1-l(i))*d2 0],[zmax zmax]*1.1,':k','linewidth',0.25);
end
plot([0 1 0.5 0],[0 0 sqrt(3)/2 0],'k','linewidth',1)
%绘制坐标轴标签
text(0.5,-0.05,'C1','HorizontalAlignment','center');
text(0.15,sqrt(3)/4+0.05,'C2','HorizontalAlignment','center','Rotation',60);
text(0.85,sqrt(3)/4+0.05,'C3','HorizontalAlignment','center','Rotation',-60);
hold off %取消叠加绘图
colorbar %色条
运行代码生成图2-14。
\[\]
图2-14 三元色谱图