弦图在python中以及r中非常常见,但是matlab中却始终没有相关函数,file exchange中也没有工作做的较为完备的弦图绘制函数(不过现在有了,我已经往上面也传了一份hiahiahia)
仅工具函数主体部分约300行,字符数约8000,能画出与r语言同等质量的弦图实属不易,希望能有个`点赞“!!!
由于工具函数过长,将被放在最后展示,以下将先展示函数用法
封面图
使用教程
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() properties ax arginlist={'colname','rowname'} vermatlab % matlab 版本: r2021a显示为2021,r2021b显示为2021.5 chordtable % table数组 datamat % 数值矩阵 colname={}; % 列名称 rowname={}; % 行名称 thetasetf thetasett % ----------------------------------------------------------- squarefhdl % 绘制下方方块的图形对象矩阵 squarethdl % 绘制下上方方块的图形对象矩阵 namefhdl % 绘制下方文本的图形对象矩阵 namethdl % 绘制上方文本的图形对象矩阵 chordmathdl % 绘制弦的图形对象矩阵 thetatickfhdl % 刻度句柄 thetatickthdl % 刻度句柄 rtickfhdl % 轴线句柄 rtickthdl % 轴线句柄 end methods function obj=chordchart(varargin) if isa(varargin{1},'matlab.graphics.axis.axes') obj.ax=varargin{1};varargin(1)=[]; else obj.ax=gca; end % 获取版本信息 tver=version('-release'); obj.vermatlab=str2double(tver(1:4))+(abs(tver(5))-abs('a'))/2; if obj.vermatlab<2017 hold on else hold(obj.ax,'on') end obj.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)]; end end else % 获取其他数据 for i=1:(length(varargin)-1) tid=ismember(obj.arginlist,varargin{i}); if any(tid) obj.(obj.arginlist{tid})=varargin{i+1}; end end tzerocell{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); end if isempty(obj.colname) for i=1:size(obj.datamat,2) obj.colname{i}=['c',num2str(i)]; end end if isempty(obj.rowname) for i=1:size(obj.datamat,1) obj.rowname{i}=['r',num2str(i)]; end end % 创建table数组 obj.chordtable=table(tzerocell{:}); obj.chordtable.variables=obj.datamat; obj.chordtable.properties.variablenames=obj.colname; obj.chordtable.properties.rownames=obj.rowname; help chordchart end end function 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:sepnumf theta1=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:sepnumt theta1=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'); end colorfunc=colorfuncfactory(flipud(summer(50))); % 绘制弦 for i=1:sepnumf for j=sepnumt:-1:1 theta1=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;end obj.thetasetf(i,j+1)=theta6; if i==1,obj.thetasett(1,j)=theta7;end obj.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)==0 set(obj.chordmathdl(i,j),'visible','off') end end % 绘制刻度线 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'); end for j=1:sepnumt tx=[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')']; end end % ================================================================= % 批量弦属性设置 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{:}); end end end % 单独弦属性设置 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))); end 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')']; end end % ----------------------------------------------------------------- % 批量上方方块属性设置 function setsquaret_prop(obj,varargin) tdmat=obj.chordtable.variables; for j=1:size(tdmat,2) set(obj.squarethdl(j),varargin{:}); end end % 单独上方方块属性设置 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{:}); end end % 单独上方方块属性设置 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{:}); end for 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); end for j=1:size(tdmat,2) set(obj.thetatickthdl(j),'visible',state); set(obj.rtickthdl(j),'visible',state); end end end end
封面图绘制代码
封面一
% 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弦图的资料请关注<计算机技术网(www.ctvol.com)!!>其它相关文章!
需要了解更多c/c++开发分享利用Matlab绘制好看的弦图,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/1237003.html