利用Matlab绘制好看的弦图
目录
- 封面图
- 使用教程
- 1.数据格式
- 2.修饰弦
- 3.圆弧状方块修饰
- 4.字体调整
- 5.显示和隐藏刻度
- 工具函数完整代码
- 封面图绘制代码
- 封面一
- 封面二
仅工具函数主体部分约300行,字符数约8000,能画出与R语言同等质量的弦图实属不易,希望能有个`点赞``!!!
【利用Matlab绘制好看的弦图】由于工具函数过长,将被放在最后展示,以下将先展示函数用法
封面图
文章图片
文章图片
使用教程
1.数据格式
数据要求为全部数值大于等于0的数值矩阵,或者
table
数组,或者数值矩阵+行列名元胞数组,首先举个数值矩阵的例子:数值矩阵
dataMat=randi([0,5],[5,4]); % 绘图CC=chordChart(dataMat); CC=CC.draw();
文章图片
这样由于没对各个对象命名,因此会自动命名为
Rn
和Cn
数值矩阵+行列名元胞数组
这是最推荐的一种格式:
dataMat=[2 0 1 2 5 1 2; 3 5 1 4 2 0 1; 4 0 5 5 2 4 3]; colName={'G1','G2','G3','G4','G5','G6','G7'}; rowName={'S1','S2','S3'}; CC=chordChart(dataMat,'rowName',rowName,'colName',colName); CC=CC.draw();
文章图片
rowName
要和矩阵的行相同大小colName
要和矩阵的列相同大小对于本列子来说第2行第3列数值是1,就说明有一份能量从
S2
流向G3
,也就在这俩之间需要画单位宽度的弦。table 数组
需要使用如下格式的table数组:
文章图片
当然,如果各个行没有命名的话依旧会自动命名的。
2.修饰弦
弦的批量修饰
弦的批量修饰可以使用
setChordProp
函数,一切Patch对象所具有的属性均可以被修饰,举个例子(修饰一下弦的颜色,边缘颜色,边缘线形状等):CC.setChordProp('EdgeColor',[.3,.3,.3],'LineStyle','--',...'LineWidth',.1,'FaceColor',[.3,.3,.3])
文章图片
弦的单独修饰
弦的单独修饰可以使用
setChordMN
函数,其中m,n值是和原始数值矩阵的行列完全对应的,举个例子(把S2
流向G4
的弦颜色更改为红色):CC.setChordMN(2,4,'FaceColor',[1,0,0])
文章图片
弦的颜色映射
使用
setChordColorByMap
函数进行颜色映射,matlab 自带的
colormap
均可用:文章图片
或者也可自行放入一个n×3大小的颜色列表,程序会自动对其进行插值:举个例子:
CC.setChordColorByMap(copper(100))
文章图片
3.圆弧状方块修饰
圆弧状方块批量修饰
使用
setSquareT_Prop
setSquareF_Prop
分别修饰上方方块和下方方块,一切Patch对象所具有的属性均可以被修饰,举个例子,上方方块批量修饰(改为黑色):
CC.setSquareT_Prop('FaceColor',[0,0,0])
文章图片
圆弧状方块单独修饰
使用
setSquareT_N
setSquareF_N
分别修饰上方方块和下方方块,举个例子,上方第二个方块单独修饰(改为红色):
CC.setSquareT_N(2,'FaceColor',[.8,0,0])
文章图片
4.字体调整
使用
setFont
函数对字体进行调整,所有text对象具有的属性均可以修饰,举个例子(更改文本的字号、字体和颜色):CC.setFont('FontSize',25,'FontName','Cambria','Color',[0,0,.8])
文章图片
5.显示和隐藏刻度
用法:
CC.tickState('on')% CC.tickState('off')
文章图片
工具函数完整代码
classdef chordChart% @author : slandarer% gzh: slandarer随笔% 使用示例:% =========================================================================% dataMat=[2 0 1 2 5 1 2; %3 5 1 4 2 0 1; %4 0 5 5 2 4 3]; % colName={'G1','G2','G3','G4','G5','G6','G7'}; % rowName={'S1','S2','S3'}; % % CC=chordChart(dataMat,'rowName',rowName,'colName',colName); % CC=CC.draw()propertiesaxarginList={'colName','rowName'}verMatlab% MATLAB 版本: R2021a显示为2021,R2021b显示为2021.5chordTable% table数组dataMat% 数值矩阵colName={}; % 列名称rowName={}; % 行名称thetaSetFthetaSetT% -----------------------------------------------------------squareFHdl% 绘制下方方块的图形对象矩阵squareTHdl% 绘制下上方方块的图形对象矩阵nameFHdl% 绘制下方文本的图形对象矩阵nameTHdl% 绘制上方文本的图形对象矩阵chordMatHdl % 绘制弦的图形对象矩阵thetaTickFHdl % 刻度句柄thetaTickTHdl % 刻度句柄RTickFHdl % 轴线句柄RTickTHdl % 轴线句柄endmethodsfunction obj=chordChart(varargin)if isa(varargin{1},'matlab.graphics.axis.Axes')obj.ax=varargin{1}; varargin(1)=[]; elseobj.ax=gca; end% 获取版本信息tver=version('-release'); obj.verMatlab=str2double(tver(1:4))+(abs(tver(5))-abs('a'))/2; if obj.verMatlab<2017hold onelsehold(obj.ax,'on')endobj.dataMat=varargin{1}; varargin(1)=[]; if isa(obj.dataMat,'table')obj.chordTable=obj.dataMat; if isempty(obj.chordTable.Properties.RowNames)for i=1:size(obj.chordTable.Variables,1)obj.rowName{i}=['R',num2str(i)]; endendelse% 获取其他数据for i=1:(length(varargin)-1)tid=ismember(obj.arginList,varargin{i}); if any(tid)obj.(obj.arginList{tid})=varargin{i+1}; endendtzerocell{1,size(obj.dataMat,2)}=zeros(size(obj.dataMat,1),1); for i=1:size(obj.dataMat,2)tzerocell{1,i}=zeros(size(obj.dataMat,1),1); endif isempty(obj.colName)for i=1:size(obj.dataMat,2)obj.colName{i}=['C',num2str(i)]; endendif isempty(obj.rowName)for i=1:size(obj.dataMat,1)obj.rowName{i}=['R',num2str(i)]; endend% 创建table数组obj.chordTable=table(tzerocell{:}); obj.chordTable.Variables=obj.dataMat; obj.chordTable.Properties.VariableNames=obj.colName; obj.chordTable.Properties.RowNames=obj.rowName; help chordChartendendfunction obj=draw(obj)obj.ax.XLim=[-1.38,1.38]; obj.ax.YLim=[-1.38,1.38]; obj.ax.XTick=[]; obj.ax.YTick=[]; obj.ax.XColor='none'; obj.ax.YColor='none'; obj.ax.PlotBoxAspectRatio=[1,1,1]; % 计算绘图所用数值tDMat=obj.chordTable.Variables; tDFrom=obj.chordTable.Properties.RowNames; tDTo=obj.chordTable.Properties.VariableNames; tDMatUni=tDMat-min(min(tDMat)); tDMatUni=tDMatUni./max(max(tDMatUni)); sep1=1/20; sep2=1/40; ratioF=sum(tDMat,2)./sum(tDMat,[1,2]); ratioF=[0,ratioF']; ratioT=[0,sum(tDMat,1)./sum(tDMat,[1,2])]; sepNumF=size(tDMat,1); sepNumT=size(tDMat,2); sepLen=pi*(1-2*sep1)*sep2; baseLenF=(pi*(1-sep2)-(sepNumF-1)*sepLen); baseLenT=(pi*(1-sep2)-(sepNumT-1)*sepLen); tColor=[61 96 137; 76 103 86]./255; % 绘制下方方块for i=1:sepNumFtheta1=2*pi-pi*sep1/2-sum(ratioF(1:i))*baseLenF-(i-1)*sepLen; theta2=2*pi-pi*sep1/2-sum(ratioF(1:i+1))*baseLenF-(i-1)*sepLen; theta=linspace(theta1,theta2,100); X=cos(theta); Y=sin(theta); obj.squareFHdl(i)=fill([1.05.*X,1.15.*X(end:-1:1)],[1.05.*Y,1.15.*Y(end:-1:1)],...tColor(1,:),'EdgeColor','none'); theta3=(theta1+theta2)/2; obj.nameFHdl(i)=text(cos(theta3).*1.28,sin(theta3).*1.28,tDFrom{i},'FontSize',12,'FontName','Arial',...'HorizontalAlignment','center','Rotation',-(1.5*pi-theta3)./pi.*180); obj.RTickFHdl(i)=plot(cos(theta).*1.17,sin(theta).*1.17,'Color',[0,0,0],'LineWidth',.8,'Visible','off'); end% 绘制上方放块for j=1:sepNumTtheta1=pi-pi*sep1/2-sum(ratioT(1:j))*baseLenT-(j-1)*sepLen; theta2=pi-pi*sep1/2-sum(ratioT(1:j+1))*baseLenT-(j-1)*sepLen; theta=linspace(theta1,theta2,100); X=cos(theta); Y=sin(theta); obj.squareTHdl(j)=fill([1.05.*X,1.15.*X(end:-1:1)],[1.05.*Y,1.15.*Y(end:-1:1)],...tColor(2,:),'EdgeColor','none'); theta3=(theta1+theta2)/2; obj.nameTHdl(j)=text(cos(theta3).*1.28,sin(theta3).*1.28,tDTo{j},'FontSize',12,'FontName','Arial',...'HorizontalAlignment','center','Rotation',-(.5*pi-theta3)./pi.*180); obj.RTickTHdl(j)=plot(cos(theta).*1.17,sin(theta).*1.17,'Color',[0,0,0],'LineWidth',.8,'Visible','off'); endcolorFunc=colorFuncFactory(flipud(summer(50))); % 绘制弦for i=1:sepNumFfor j=sepNumT:-1:1theta1=2*pi-pi*sep1/2-sum(ratioF(1:i))*baseLenF-(i-1)*sepLen; theta2=2*pi-pi*sep1/2-sum(ratioF(1:i+1))*baseLenF-(i-1)*sepLen; theta3=pi-pi*sep1/2-sum(ratioT(1:j))*baseLenT-(j-1)*sepLen; theta4=pi-pi*sep1/2-sum(ratioT(1:j+1))*baseLenT-(j-1)*sepLen; tRowV=tDMat(i,:); tRowV=[0,tRowV(end:-1:1)./sum(tRowV)]; tColV=tDMat(:,j)'; tColV=[0,tColV./sum(tColV)]; % 贝塞尔曲线断点计算theta5=(theta2-theta1).*sum(tRowV(1:(sepNumT+1-j)))+theta1; theta6=(theta2-theta1).*sum(tRowV(1:(sepNumT+2-j)))+theta1; theta7=(theta3-theta4).*sum(tColV(1:i))+theta4; theta8=(theta3-theta4).*sum(tColV(1:i+1))+theta4; tPnt1=[cos(theta5),sin(theta5)]; tPnt2=[cos(theta6),sin(theta6)]; tPnt3=[cos(theta7),sin(theta7)]; tPnt4=[cos(theta8),sin(theta8)]; if j==sepNumT,obj.thetaSetF(i,1)=theta5; endobj.thetaSetF(i,j+1)=theta6; if i==1,obj.thetaSetT(1,j)=theta7; endobj.thetaSetT(i+1,j)=theta8; % 计算曲线tLine1=bezierCurve([tPnt1; 0,0; tPnt3],200); tLine2=bezierCurve([tPnt2; 0,0; tPnt4],200); tline3=[cos(linspace(theta6,theta5,100))',sin(linspace(theta6,theta5,100))']; tline4=[cos(linspace(theta7,theta8,100))',sin(linspace(theta7,theta8,100))']; obj.chordMatHdl(i,j)=fill([tLine1(:,1); tline4(:,1); tLine2(end:-1:1,1); tline3(:,1)],...[tLine1(:,2); tline4(:,2); tLine2(end:-1:1,2); tline3(:,2)],...colorFunc(tDMatUni(i,j)),'FaceAlpha',.3,'EdgeColor','none'); if tDMat(i,j)==0set(obj.chordMatHdl(i,j),'Visible','off')endend% 绘制刻度线tX=[cos(obj.thetaSetF(i,:)).*1.17; cos(obj.thetaSetF(i,:)).*1.19; nan.*ones(1,sepNumT+1)]; tY=[sin(obj.thetaSetF(i,:)).*1.17; sin(obj.thetaSetF(i,:)).*1.19; nan.*ones(1,sepNumT+1)]; obj.thetaTickFHdl(i)=plot(tX(:),tY(:),'Color',[0,0,0],'LineWidth',.8,'Visible','off'); endfor j=1:sepNumTtX=[cos(obj.thetaSetT(:,j)').*1.17; cos(obj.thetaSetT(:,j)').*1.19; nan.*ones(1,sepNumF+1)]; tY=[sin(obj.thetaSetT(:,j)').*1.17; sin(obj.thetaSetT(:,j)').*1.19; nan.*ones(1,sepNumF+1)]; obj.thetaTickTHdl(j)=plot(tX(:),tY(:),'Color',[0,0,0],'LineWidth',.8,'Visible','off'); end% 贝塞尔函数function pnts=bezierCurve(pnts,N)t=linspace(0,1,N); p=size(pnts,1)-1; coe1=factorial(p)./factorial(0:p)./factorial(p:-1:0); coe2=((t).^((0:p)')).*((1-t).^((p:-1:0)')); pnts=(pnts'*(coe1'.*coe2))'; end% 渐变色句柄生成函数function colorFunc=colorFuncFactory(colorList)x=(0:size(colorList,1)-1)./(size(colorList,1)-1); y1=colorList(:,1); y2=colorList(:,2); y3=colorList(:,3); colorFunc=@(X)[interp1(x,y1,X,'linear')',interp1(x,y2,X,'linear')',interp1(x,y3,X,'linear')']; endend% =================================================================% 批量弦属性设置function setChordProp(obj,varargin)tDMat=obj.chordTable.Variables; for i=1:size(tDMat,1)for j=1:size(tDMat,2)set(obj.chordMatHdl(i,j),varargin{:}); endendend% 单独弦属性设置function setChordMN(obj,m,n,varargin)set(obj.chordMatHdl(m,n),varargin{:}); end% 根据colormap映射颜色function setChordColorByMap(obj,colorList)tDMat=obj.chordTable.Variables; tDMatUni=tDMat-min(min(tDMat)); tDMatUni=tDMatUni./max(max(tDMatUni)); colorFunc=colorFuncFactory(colorList); for i=1:size(tDMat,1)for j=1:size(tDMat,2)set(obj.chordMatHdl(i,j),'FaceColor',colorFunc(tDMatUni(i,j))); endend% 渐变色句柄生成函数function colorFunc=colorFuncFactory(colorList)x=(0:size(colorList,1)-1)./(size(colorList,1)-1); y1=colorList(:,1); y2=colorList(:,2); y3=colorList(:,3); colorFunc=@(X)[interp1(x,y1,X,'linear')',interp1(x,y2,X,'linear')',interp1(x,y3,X,'linear')']; endend% -----------------------------------------------------------------% 批量上方方块属性设置function setSquareT_Prop(obj,varargin)tDMat=obj.chordTable.Variables; for j=1:size(tDMat,2)set(obj.squareTHdl(j),varargin{:}); endend% 单独上方方块属性设置function setSquareT_N(obj,n,varargin)set(obj.squareTHdl(n),varargin{:}); end% 批量下方方块属性设置function setSquareF_Prop(obj,varargin)tDMat=obj.chordTable.Variables; for i=1:size(tDMat,1)set(obj.squareFHdl(i),varargin{:}); endend% 单独上方方块属性设置function setSquareF_N(obj,n,varargin)set(obj.squareFHdl(n),varargin{:}); end% -----------------------------------------------------------------% 字体设置function setFont(obj,varargin)tDMat=obj.chordTable.Variables; for i=1:size(tDMat,1)set(obj.nameFHdl(i),varargin{:}); endfor j=1:size(tDMat,2)set(obj.nameTHdl(j),varargin{:}); end end% -----------------------------------------------------------------% 刻度开关function tickState(obj,state)tDMat=obj.chordTable.Variables; for i=1:size(tDMat,1)set(obj.thetaTickFHdl(i),'Visible',state); set(obj.RTickFHdl(i),'Visible',state); endfor j=1:size(tDMat,2)set(obj.thetaTickTHdl(j),'Visible',state); set(obj.RTickTHdl(j),'Visible',state); endendendend
封面图绘制代码
封面一
% demo 1% @author : slandarer% gzh: slandarer随笔dataMat=[2 0 1 2 5 1 2; 3 5 1 4 2 0 1; 4 0 5 5 2 4 3]; colName={'G1','G2','G3','G4','G5','G6','G7'}; rowName={'S1','S2','S3'}; CC=chordChart(dataMat,'rowName',rowName,'colName',colName); CC=CC.draw(); CC.setFont('FontSize',17,'FontName','Cambria')CC.tickState('on')
文章图片
封面二
% demo 2% @author : slandarer% gzh : slandarer随笔dataMat=[2 0 1 2 5 1 2; 3 5 1 4 2 0 1; 4 0 5 5 2 4 3]; colName={'G1','G2','G3','G4','G5','G6','G7'}; rowName={'S1','S2','S3'}; CC=chordChart(dataMat,'rowName',rowName,'colName',colName); CC=CC.draw(); % 弦属性设置 ===============================================================% CC.setChordProp('EdgeColor',[.3,.3,.3],'LineStyle','--',...%'LineWidth',.1,'FaceColor',[.3,.3,.3])% CC.setChordMN(2,4,'FaceColor',[1,0,0])CC.setChordColorByMap(copper(100))% 方块属性设置 =============================================================CC.setSquareT_Prop('FaceColor',[0,0,0])CC.setSquareT_N(2,'FaceColor',[.8,0,0])% CC.setSquareF_Prop('FaceColor',[0,0,0])% CC.setSquareF_N(2,'FaceColor',[.8,0,0])% 字体设置 =================================================================CC.setFont('FontSize',17,'FontName','Cambria','Color',[0,0,.8])% 刻度开关设置 =============================================================CC.tickState('on')
文章图片
以上就是利用Matlab绘制好看的弦图的详细内容,更多关于Matlab弦图的资料请关注脚本之家其它相关文章!
推荐阅读
- Matlab实现带竖线散点的核密度图的绘制
- #|【路径优化】基于改进的RRT算法的全局路径规划(Matlab代码实现)
- iOS绘制渐变色背景
- lesson1-绘制直方图-乘客数据
- 机器人控制算法|机器人控制算法二之matlab工具箱机械臂运动学正逆矩阵解具体分析
- 机器学习|吴恩达机器学习作业一(利用多元线性回归模型实现房价预测(python实现))
- matlab|matlab 二维高斯滤波 傅里叶_基于相关滤波的目标跟踪算法
- matlab子域边界,matlab tool box function
- Unity和微软建立云合作伙伴关系,利用Azure赋能全球的创作者
- 利用现有数据库管理系统创建一个安全的分布式数据库集群