MATLAB | 如何用MATLAB绘制这样有气泡感的网络图
今天给大家带来一款用来绘制有气泡感的网络图的工具函数,绘制效果如下:

花里胡哨的,气泡大小代表流入流出数据量综合,不同颜色的气泡代表属于不同类,两个气泡之间有连线代表有数据流动,连线透明度代表流动数据量,连线的颜色是有方向性的渐变色。
依旧完整代码放在文末。
教程部分
0 数据准备
数据需要的关系矩阵需要的是反对称矩阵:
% 随机生成100x100的反对角矩阵
Data=(rand(100)-.5).*(rand(100)>.978);
Data(1:30,:)=Data(1:30,:).*3;
Data=tril(Data)-tril(Data)';
% 生成100x1列向量,分类标签为1-10
Class=(1:10).*ones(10,1);
Class=Class(:);
1 基础绘图
两行代码完事:
% 基础绘图
BD=bubbleDigraph(Data,Class);
BD=BD.draw();

2 气泡大小
可以使用bubblesize函数设置气泡大小范围,例如:
bubblesize([5,40])

3 气泡颜色
使用setBubbleColor函数设置颜色:
BD.setBubbleColor(turbo(10))

4 气泡其他属性
可以使用setBubble函数进行设置,bubblechart图形对象具有的属性均可以修改:
BD.setBubble('MarkerFaceAlpha',.2,'MarkerEdgeColor',[0,0,0])

5 连线配色
直接使用colormap函数即可设置:
colormap(bone)

6 添加节点及类标签
分别使用:
- NodeName
- ClassName
俩属性设置两种标签:
for i=1:100nodeName{i}=[num2str(Class(i)),'-',num2str(i)];
end
className={'AAAAA','BBBBB','CCCCC','DDDDD','EEEEE','FFFFF','GGGGG','HHHHH','IIIII','JJJJJ'};BD=bubbleDigraph(Data,Class,'NodeName',nodeName,'ClassName',className);
BD=BD.draw();bubblesize([5,25])

7 标签距离
分别通过:
- RNode
- RClass
俩属性设置两种标签距离中心的距离:
BD=bubbleDigraph(Data,Class,'NodeName',nodeName,'ClassName',className,'RClass',1.38,'RNode',1.2);
BD=BD.draw();

8 设置字体
分别使用:
- setNodeLabel
- setClassLabel
俩函数设置两种标签的属性:
BD.setNodeLabel('FontName','Cambria','Color',[0,0,.8])
BD.setClassLabel('FontName','Cambria','Color',[.8,0,0],'FontSize',14)

完整代码
classdef bubbleDigraph
% @author : slandarer
% gzh : slandarer随笔
% Zhaoxu Liu / slandarer (2023). bubble digraph
% (https://www.mathworks.com/matlabcentral/fileexchange/125140-bubble-digraph),
% MATLAB Central File Exchange. 检索来源 2023/2/21.propertiesax,arginList={'ColorOrder','Colormap','ClassName','NodeName','BubbleSize','RClass','RNode'}ClassName % 类名称NodeName % 节点名称% 节点配色ColorOrder=[0.6510 0.8078 0.8902; 0.1216 0.4706 0.7059; 0.6980 0.8745 0.54120.2000 0.6275 0.1725; 0.9843 0.6039 0.6000; 0.8902 0.1020 0.10980.9922 0.7490 0.4353; 1.0000 0.4980 0; 0.7922 0.6980 0.83920.4157 0.2392 0.6039; 1.0000 1.0000 0.6000; 0.6941 0.3490 0.1569];% 连线配色Colormap=[1.0000 0.9686 0.9529; 0.9980 0.9454 0.9307; 0.9960 0.9221 0.9084; 0.9939 0.8988 0.88610.9920 0.8750 0.8630; 0.9910 0.8477 0.8336; 0.9900 0.8204 0.8043; 0.9890 0.7930 0.7750; 0.9877 0.7629 0.7502; 0.9857 0.7245 0.7390; 0.9837 0.6860 0.7279; 0.9817 0.6476 0.7168; 0.9793 0.6027 0.7022; 0.9762 0.5470 0.6820; 0.9732 0.4913 0.6617; 0.9701 0.4357 0.6415; 0.9555 0.3815 0.6263; 0.9292 0.3289 0.6162; 0.9028 0.2763 0.6061; 0.8765 0.2237 0.5960; 0.8369 0.1717 0.5763; 0.7894 0.1201 0.5510; 0.7418 0.0684 0.5257; 0.6942 0.0168 0.5004; 0.6429 0.0039 0.4888; 0.5903 0.0039 0.4817; 0.5376 0.0039 0.4746; 0.4850 0.0039 0.4676; 0.4350 0.0030 0.4552; 0.3855 0.0020 0.4420; 0.3359 0.0010 0.4288; 0.2863 0 0.4157];Data,Class % 有向图及节点分类BubbleSize=[5,25]; % 节点气泡大小范围[min,max]LineWidth=1.5; % 连接线粗细AlphaLim=[.1,.9];ClassSet,ClassNum,RClass=1.25;RNode=1.08;ColorList;bubbleHdl,nodeLabelHdl,classLabelHdlendmethodsfunction obj=bubbleDigraph(Data,Class,varargin)obj.Data=Data;obj.Class=Class(:);obj.ClassSet=unique(Class);obj.ClassNum=length(obj.ClassSet);for i=1:size(obj.Data,1)obj.NodeName{i}='';endfor i=1:obj.ClassNumobj.ClassName{i}='';end% 获取其他数据disp(char([64 97 117 116 104 111 114 32 58 32,...115 108 97 110 100 97 114 101 114]))for i=1:2:(length(varargin)-1)tid=ismember(obj.arginList,varargin{i});if any(tid)obj.(obj.arginList{tid})=varargin{i+1};endendif obj.ClassNum>size(obj.ColorOrder,1)obj.ColorOrder=[obj.ColorOrder;rand([obj.ClassNum,3])];endendfunction obj=draw(obj)obj.ax=gca;hold on;colormap(obj.Colormap)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;fig.Color=[1,1,1];if max(fig.Position(3:4))<600fig.Position(3:4)=1.8.*fig.Position(3:4);fig.Position(1:2)=fig.Position(1:2)./3;end% 绘制气泡thetaList=linspace(0,2*pi,size(obj.Data,1)+1);thetaList(end)=[];XList=cos(thetaList);YList=sin(thetaList);obj.bubbleHdl=bubblechart(XList,YList,sum(abs(obj.Data)));bubblesize(obj.BubbleSize)obj.ColorList=zeros(size(obj.Data,1),3);for i=1:length(obj.ClassSet)obj.ColorList(obj.Class==obj.ClassSet(i),:)=...repmat(obj.ColorOrder(i,:),sum(obj.Class==obj.ClassSet(i)),1);endobj.bubbleHdl.CData=obj.ColorList;% 绘制连线alphaData=abs(obj.Data);alphaData=alphaData-min(min(alphaData));alphaData=alphaData./max(max(alphaData));alphaData=alphaData.*(obj.AlphaLim(2)-obj.AlphaLim(1))+obj.AlphaLim(1);for i=1:size(obj.Data,1)for j=1:i-1if obj.Data(i,j)~=0bezierX=[cos(thetaList(i)),0,cos(thetaList(j))].*.93;bezierY=[sin(thetaList(i)),0,sin(thetaList(j))].*.93;bezierPnts=bezierCurve([bezierX',bezierY'],100);bezierX=[bezierPnts(:,1);nan];bezierY=[bezierPnts(:,2);nan];fill(bezierX,bezierY,linspace(-1,1,101).*obj.Data(i,j)./abs(obj.Data(i,j)),'EdgeColor','interp',...'LineWidth',obj.LineWidth,'EdgeAlpha',alphaData(i,j))endendend% 绘制节点标签for i=1:size(obj.Data,1)Ti=thetaList(i);rotation=Ti/pi*180;if rotation>90&&rotation<270rotation=rotation+180;obj.nodeLabelHdl(i)=text(cos(Ti).*obj.RNode,sin(Ti).*obj.RNode,obj.NodeName{i},...'Rotation',rotation,'HorizontalAlignment','right','FontSize',9);elseobj.nodeLabelHdl(i)=text(cos(Ti).*obj.RNode,sin(Ti).*obj.RNode,obj.NodeName{i},...'Rotation',rotation,'FontSize',9);endend% 绘制类标签for i=1:obj.ClassNumCTi=mean(thetaList(obj.Class==obj.ClassSet(i)));rotation=CTi/pi*180;if rotation>0&&rotation<180obj.classLabelHdl(i)=text(cos(CTi).*obj.RClass,sin(CTi).*obj.RClass,obj.ClassName{i},'FontSize',14,'FontName','Arial',...'HorizontalAlignment','center','Rotation',-(.5*pi-CTi)./pi.*180);elseobj.classLabelHdl(i)=text(cos(CTi).*obj.RClass,sin(CTi).*obj.RClass,obj.ClassName{i},'FontSize',14,...'HorizontalAlignment','center','Rotation',-(1.5*pi-CTi)./pi.*180);endend% 贝塞尔函数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))';endend% 修改气泡颜色function obj=setBubbleColor(obj,ColorList)obj.ColorOrder=ColorList;for i=1:length(obj.ClassSet)obj.ColorList(obj.Class==obj.ClassSet(i),:)=...repmat(obj.ColorOrder(i,:),sum(obj.Class==obj.ClassSet(i)),1);endset(obj.bubbleHdl,'CData',obj.ColorList);end% 修改气泡其他属性function obj=setBubble(obj,varargin)set(obj.bubbleHdl,varargin{:});end% 设置标签function setNodeLabel(obj,varargin)for i=1:size(obj.Data,1)set(obj.nodeLabelHdl(i),varargin{:});endendfunction setClassLabel(obj,varargin)for i=1:obj.ClassNumset(obj.classLabelHdl(i),varargin{:});endendend
% @author : slandarer
% gzh : slandarer随笔
% Zhaoxu Liu / slandarer (2023). bubble digraph
% (https://www.mathworks.com/matlabcentral/fileexchange/125140-bubble-digraph),
% MATLAB Central File Exchange. 检索来源 2023/2/21.
end
完
编程不易,希望大家该点赞的点赞,该在看的在看!!
未经允许本代码请勿作商业用途,引用的话可以引用我file exchange上的链接,可使用如下格式:
Zhaoxu Liu / slandarer (2023). bubble digraph (https://www.mathworks.com/matlabcentral/fileexchange/125140-bubble-digraph), MATLAB Central File Exchange. 检索来源 2023/2/21.
若转载请保留以上file exchange链接及本文链接!!!!!
相关文章:
MATLAB | 如何用MATLAB绘制这样有气泡感的网络图
今天给大家带来一款用来绘制有气泡感的网络图的工具函数,绘制效果如下: 花里胡哨的,气泡大小代表流入流出数据量综合,不同颜色的气泡代表属于不同类,两个气泡之间有连线代表有数据流动,连线透明度代表流动数…...
Linux 远程登录
Linux 一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的 Linux 服务器。 这时我们就需要远程登录到Linux服务器来管理维护系统。 Linux 系统中是通过 ssh 服务实现的远程登录功能,默认 ssh 服务端口号为 22。 Window 系统…...
SAP中BOM基础数量及组件数量单位比例关系的注意事项
下图是BOM展开功能CS11在正式系统和测试系统的截图。从截图中的对比不难看出,最下级的原材料A20981-110在组件的数量为1,实际按BOM中的设定比例折算,应该是1个成品,对应需要0.125件原材料。但这里显示的并不是0.125PC,…...
华为OD机试真题Python实现【最大相连男生数】真题+解题思路+代码(20222023)
最大相连男生数 题目 学校组织活动,将学生排成一个矩形方阵。 请在矩形方阵中找到最大的位置相连的男生数量。 这个相连位置在一个直线上,方向可以是水平的、垂直的、成对角线的或者反对角线的。 注:学生个数不会超过 10000。 🔥🔥🔥🔥🔥👉👉👉👉👉�…...
Vue使用ElementUI对表单元素进行自定义校验
前言 在使用ElementUI的表单元素时候,除了做一些简单的非空处理校验,在一些特殊的场合,还需要我们做一些自定义校验。 其实ElementUI不仅提供了基本的非空校验,也对我们提供了自定义检验。 在使用的时候还是遇到了一些坑&#…...
linux的文件权限介绍
文件权限 在linux终端输入 ls -lh 出现下面界面 介绍 基本信息 其中的开头代表着文件类型和权限 而 root 和kali 则分别代表用户名和用户组名用户名顾名思义就是这个文件属于哪一个用户用户组是说自己在写好一个文件后,这个文件是属于该用户所有,…...
支付系统中的设计模式03:模板方法模式
在上一节末尾,留了一个需求问题,就是老板提出的「支付前锁定账户,支付后增加积分」这个需求「3」没有解决。有些文章写得比较好的人其实会有一些固定的结构格式,比如总分总、总分、分总、并列、对照、递进等等。这种固定的结构格式,就是文章的模板。把它挪到编程中,也是一…...
【黏住用户的不是小红书,而是它背后的那些人】
最近在研究CDC线下城市联盟的事情,周六与本地组织做了一场简单的活动,没想到现场开发者热情暴涨,现场沟通了很多,大家普遍有两层需求: 1.加入圈子沟通 2.互助学习提升 CDC,也就是线下圈子,如…...
基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试(中篇)
3.2 SPI硬件时序方式 上面的3.1小节是采用SPI模拟时序驱动SD NAND,STM32本身集成有SPI硬件模块,可以直接利用STM32硬件SPI接口读写。 下面贴出底层的适配代码。 上面贴出的驱动代码里,已经将驱动接口部分和协议逻辑部分区分开了,替…...
0基础学插画是报班还是自学
学插画0基础是报班还是自学,众所周知,报班一定是提升插画水平的最有效途径,如果有经济能力,建议报班!那么报哪些插画课程班比较靠谱呢?同时给大家梳理了国内最新5大插画班排行榜,各有优势和特色…...
【Spring Cloud Alibaba】000-Spring Cloud Alibaba 问题集锦[持续更新]
【Spring Cloud Alibaba】000-Spring Cloud Alibaba 问题集锦[持续更新] 文章目录【Spring Cloud Alibaba】000-Spring Cloud Alibaba 问题集锦[持续更新]一、微服务相关1、什么是单体应用2、单体应用优缺点优点缺点3、单体应用使用场景4、什么是微服务架构5、微服务的特性6、微…...
Java使用MD5加盐对密码进行加密处理,附注册和登录加密解密处理
前言 在开发的时候,有一些敏感信息是不能直接通过明白直接保存到数据库的。最经典的就是密码了。如果直接把密码以明文的形式入库,不仅会泄露用户的隐私,对系统也是极其的不厉,这样做是非常危险的。 那么我们就需要对这些铭文进…...
vue3组件篇 Select
文章目录组件介绍何时使用基本功能组件代码参数说明事件关于dxui组件库组件介绍 何时使用 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。 当选项少时(少于 5 项),建议直接将…...
华为OD机试 - 员工出勤(Python) | 机试题+算法思路+考点+代码解析 【2023】
员工出勤 题目 公司用一个字符串来标识员工的出勤信息 absent: 缺勤 late: 迟到 leaveearly:早退 present: 正常上班 现需根据员工出勤信息,判断本次是否能获得出勤奖, 能获得出勤奖的条件如下: 缺勤不超过1次没有连续的迟到/早退任意连续7次考勤,缺勤/迟到/早退,不超过3次…...
力扣:27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面…...
华为OD机试 - 剩余可用字符集(Python) | 机试题+算法思路+考点+代码解析 【2023】
剩余可用字符集 题目 给定两个字符集合 一个是全量字符集 一个是已占用字符集 已占用字符集中的字符不能再使用 要求输出剩余可用字符集 输入 输入一个字符串 一定包含@ @前为全量字符集 @后的为已占用字符集已占用字符集中的字符 一定是全量字符集中的字符 字符集中的字符跟…...
金三银四丨黑蛋老师带你剖析-安全开发岗
作者丨黑蛋在之前呢,我们聊了二进制这块的病毒岗位,漏洞岗位,逆向岗位以及CTF这块的岗位。今天我们就来聊一聊安全开发类的工作岗位。首先网络安全方向中安全开发岗位都有哪些,安全开发主要指安全研发工程师或安全开发工程师&…...
isNaN、Number.isNaN、isFinite、Number.isFinite
isNaN和Number.isNaN这两者都是为了判断参数是否为NaN类型。isNaN的实现原理是:通过Number()方法,尝试将参数转换成Number类型,如果成功返回false,如果失败返回true。isNaN只是判断传入的参数是否能转换成数字,并不是严…...
MyBatis分页插件
目录 分页插件 Mybatis插件典型适用场景 实现思考 第一个问题 第二个问题 自定义分页插件 分页插件使用 添加pom依赖 插件注册 调用 代理和拦截是怎么实现的 PageHelper 原理 分页插件 MyBatis 通过提供插件机制,让我们可以根据自己的需要去增强MyBati…...
Vue组件间通信的四种方式(函数回调,自定义事件,事件总线,消息订阅与发布)
目录 概述 props配置项-回调函数实现 自定义事件实现 事件总线实现 消息订阅与发布实现(pubsub-js库) 概述 在组件化编程中,组件间的通信是重要的,我们可以有四种方式实现组件间的通信。 分别是:函数回调&…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
