MATLAB | 全网唯一! 又双叒叕一种弦图绘制
Posted slandarer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MATLAB | 全网唯一! 又双叒叕一种弦图绘制相关的知识,希望对你有一定的参考价值。
前几天有粉丝问我这种图能不能画:
大体看了一下就是有联系的两个元素之间连线,同时将不同类用不同颜色划分,于是又双叒叕了一个工具函数:
绘制效果
教程部分
基础使用
输入数据要求一个nxn大小的0-1矩阵,代表各个元素之间有没有连线,同时还需要一个nx1大小的Class
列表代表每个元素属于哪一类,举个简单的例子:
% 生成随机200x200对称0-1矩阵
Data=rand(200,200)>.992;
Data=(Data+Data')>0;
% 生成200x1随机分类编号
Class=randi([1,5],[200,1]);
CC=circosChart(Data,Class);
CC=CC.draw();
修改颜色
以下两种写法等价:
colorList=[78 101 155;
138 140 191;
184 168 207;
231 188 198;
253 207 158]./255;
CC=circosChart(Data,Class,'ColorOrder',colorList);
CC=CC.draw();
CC=circosChart(Data,Class);
CC=CC.draw();
colorList=[78 101 155;
138 140 191;
184 168 207;
231 188 198;
253 207 158]./255;
CC.setColor(1:5,colorList)
除颜色外其他线属性设置
使用setLine
修饰其他属性,'Line’对象具有的属性均可以修饰,例如改变粗细:
CC.setLine('LineWidth',5)
添加和修改标签
设置
- partNameList
- classNameList
俩属性设置标签:
% 生成随机200x200对称0-1矩阵
Data=rand(200,200)>.992;
Data=(Data+Data')>0;
% 生成200x1随机分类编号
Class=randi([1,5],[200,1]);
for i=1:200
partNamei=[num2str(Class(i)),'-',num2str(i)];
end
className='AAAAA','BBBBB','CCCCC','DDDDD','EEEEE';
CC=circosChart(Data,Class,'PartName',partName,'ClassName',className);
CC=CC.draw();
修饰标签
使用:
- setPartLabel
- setClassLabel
俩函数修饰文本标签,例如:
CC.setPartLabel('Color',[0,0,.8],'FontName','Cambria')
CC.setClassLabel('Color',[.8,0,0],'FontName','Cambria','FontSize',25)
一个实例
展示 π \\pi π小数点后500和1000位数字前后连接情况:500个点的时候我们发现7出现次数似乎格外的少,本来以为写错了,结果算了一下就只出现了36次,确实是出现的次数比较少:
% demo 1 pi小数点后1000个数值前后连接状况
piStr=['1415926535897932384626433832795028841971693993751058209749445923078',...
'1640628620899862803482534211706798214808651328230664709384460955058',...
'2231725359408128481117450284102701938521105559644622948954930381964',...
'4288109756659334461284756482337867831652712019091456485669234603486',...
'1045432664821339360726024914127372458700660631558817488152092096282',...
'9254091715364367892590360011330530548820466521384146951941511609433',...
'0572703657595919530921861173819326117931051185480744623799627495673',...
'5188575272489122793818301194912983367336244065664308602139494639522',...
'4737190702179860943702770539217176293176752384674818467669405132000',...
'5681271452635608277857713427577896091736371787214684409012249534301',...
'4654958537105079227968925892354201995611212902196086403441815981362',...
'9774771309960518707211349999998372978049951059731732816096318595024',...
'4594553469083026425223082533446850352619311881710100031378387528865',...
'8753320838142061717766914730359825349042875546873115956286388235378',...
'75937519577818577805321712268066130019278766111959092164201999'];
Class=abs(piStr(1:1000))-47; % 类要求从1开始而非0因此这里减去47
Data=diag(ones(1,999),-1);
className='0','1','2','3','4','5','6','7','8','9';
colorOrder=[239,65,75;230,115,48;229,158,57;232,136,85;239,199,97;
144,180,116;78,166,136;81,140,136;90,118,142;43,121,159]./255;
CC=circosChart(Data,Class,'ClassName',className,'ColorOrder',colorOrder);
CC=CC.draw();
ax=gca;
ax.Color=[0,0,0];
CC.setClassLabel('Color',[1,1,1],'FontSize',25,'FontName','Cambria')
CC.setLine('LineWidth',.7)
工具函数完整代码
classdef circosChart
% @author : slandarer
% gzh : slandarer随笔
properties
ax,arginList='ColorOrder','ClassName','PartName'
ColorOrder=[80,118,169;226,144,50;127,167,58;242,86,54;126,109,167;
196,98,37;74,148,189;255,182,46;161,86,144;134,138,33;
240,73,53;90,123,207;254,147,44;186,79,115;35,170,102]./255;
ClassName,PartName
Data,Class,indexInClass,colorSet=[]
classSet,classNum,classSize,classRatio,classTheta
lineHdl,partLabelHdl,classLabelHdl,scatterHdl
end
methods
function obj=circosChart(Data,Class,varargin)
obj.Data=Data;
obj.Class=Class(:);
obj.classSet=unique(Class);
obj.classNum=length(obj.classSet);
obj.indexInClass=zeros(length(obj.Class),1);
% 计算比例
for i=1:obj.classNum
tClassBool=obj.classSet(i)==obj.Class;
tCumsumBool=cumsum(tClassBool);
obj.classSize(i)=sum(tClassBool);
obj.indexInClass(tClassBool)=tCumsumBool(tClassBool);
end
obj.classRatio=obj.classSize./sum(obj.classSize);
disp(char([64 97 117 116 104 111 114 32 58 32 115 108 97 110 100 97 114 101 114]))
obj.ColorOrder=[obj.ColorOrder;rand([obj.classNum,3])];
for i=1:size(obj.Data,1)
obj.PartNamei='';
end
for i=1:obj.classNum
obj.ClassNamei=['Class ',num2str(i)];
end
% 获取其他数据
for i=1:2:(length(varargin)-1)
tid=ismember(obj.arginList,varargini);
if any(tid)
obj.(obj.arginListtid)=varargini+1;
end
end
end
function obj=draw(obj)
obj.ax=gca;hold on
obj.ax.XLim=[-1.2,1.2];
obj.ax.YLim=[-1.2,1.2];
obj.ax.XTick=[];
obj.ax.YTick=[];
obj.ax.XColor='none';
obj.ax.YColor='none';
obj.ax.PlotBoxAspectRatio=[1,1,1];
% 调整初始界面大小
fig=obj.ax.Parent;
if max(fig.Position(3:4))<600
fig.Position(3:4)=1.8.*fig.Position(3:4);
fig.Position(1:2)=fig.Position(1:2)./3;
end
sepTheta=2/30/obj.classNum;
cumTheta=[0,28/30*cumsum(obj.classRatio)];
if isempty(obj.PartName1)&&isempty(obj.PartName2)
tdis=1.1;
else
tdis=1.22;
end
% 计算每一类中每一个元素的角度
for i=1:obj.classNum
obj.classTheta(i).T=linspace(sepTheta*i+cumTheta(i),sepTheta*i+cumTheta(i+1),obj.classSize(i)).*2.*pi;
obj.scatterHdl(i)=scatter(cos(obj.classTheta(i).T),sin(obj.classTheta(i).T),30,'filled','CData',obj.ColorOrder(i,:),'MarkerEdgeColor','none');
CTi=mean(obj.classTheta(i).T);
rotation=CTi/pi*180;
if rotation>0&&rotation<180
obj.classLabelHdl(i)=text(cos(CTi).*tdis,sin(CTi).*tdis,obj.ClassNamei,'FontSize',14,'FontName','Arial',...
'HorizontalAlignment','center','Rotation',-(.5*pi-CTi)./pi.*180);
else
obj.classLabelHdl(i)=text(cos(CTi).*tdis,sin(CTi).*tdis,obj.ClassNamei,'FontSize',14,...
'HorizontalAlignment','center','Rotation',-(1.5*pi-CTi)./pi.*180);
end
end
% 绘制文字
for i=1:size(obj.Data,1)
Ci=obj.Class(i);Pi=obj.indexInClass(i);
Ti=obj.classTheta(Ci).T(Pi);
rotation=Ti/pi*180;
if rotation>90&&rotation<270
rotation=rotation+180;
obj.partLabelHdl(i)=text(cos(Ti).*1.03,sin(Ti).*1.03,obj.PartNamei,'Rotation',rotation,'HorizontalAlignment','right','FontSize',8);
else
obj.partLabelHdl(i)=text(cos(Ti).*1.03,sin(Ti).*1.03,obj.PartNamei,'Rotation',rotation,'FontSize',8);
end
end
% 计算类与类之间的渐变色
t2=linspace(0,1,200);t1=1-t2;
for i=1:obj.classNum
for j以上是关于MATLAB | 全网唯一! 又双叒叕一种弦图绘制的主要内容,如果未能解决你的问题,请参考以下文章