因为对matlab绘图函数不熟悉,整整花了6个多小时,才终于绘制出了封面那张理想的图。💺
文章目录
一、最终的作图成果二、作图步骤第一步:读取所有数据第二步:将数据包装入结构体第三步:绘制交通路线图(不含散点)第四步:筛选第一问所要用到的散点数据第五步:集中绘制散点图第六步:细节优化→图例修整、坐标说明+标题①图例修整②坐标说明+标题四、总结:五、完整源码(/5/3补充)六、参考附录:敲到码穷处,坐看云起时。🍋 🍋 🍋
数学建模系列文章——总结篇:《数模美一国一退役选手的经验分享[纪念版]》.
一、最终的作图成果
这是国赛数模B题《交巡警服务平台的设置与调度》,用第一问给的数据来作的图。🍬
接下来我将依次讲解其步骤,作图的详细说明在代码的注释里。🍬
二、作图步骤
第一步:读取所有数据
clc,clear,close all;[all_data_1,QY] = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',1,'A2:E583'); % 附件1的数据all_data_2 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',2,'A2:B929'); % 附件2的数据all_data_3 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',3,'B2:B81'); % 附件3的数据all_data_4_1 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',4,'B2:B18'); % 附件4的数据all_data_4_2 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',4,'C2:C14'); % 附件4的数据ind = all_data_1(:,1);% 数据点的编号zuo_x = all_data_1(:,2); % 数据点的横坐标zuo_y = all_data_1(:,3); % 数据点的纵坐标QuYu = QY;% 数据点所在的区域【一共有A、B、...、F七个区域】FaAnLv = all_data_1(:,5); % 数据点的发案率QiDian_ind = all_data_2(:,1);% 交通道路的起点编号ZhongDian_ind = all_data_2(:,2); % 交通道路的终点编号
说明:①Excel数据 需要放在 matlab当前运行的文件夹里面。
②xlsread()函数的用法详见本文最后的 参考附录【5】📗。
③数据在文章最后的 参考附录【7】 📘。
第二步:将数据包装入结构体
% 第一种添加结构体成员的方法t = 1; % 用 t 来记录结构体的序号for i = 1:size(ind)% Table(t) = struct('ind',ind(i),'ZuoBiao',[zuo_x,zuo_y],'QuYu',QuYu(i),'FaAnLv',FaAnLv(i));Table(t) = struct('ind',ind(i),'X',zuo_x(i),'Y',zuo_y(i),'QuYu',QuYu(i),'FaAnLv',FaAnLv(i));t = t + 1;end%---------------------------------% 第二种添加结构体成员的方法---------for i = 1:size(ind)Table(i).NextJieDian = []; % 先初始化endfor i = 1:size(all_data_2,1) % 遍历每条边,然后把 起点 和 终点 连起来【双边都要连】Table(QiDian_ind(i)).NextJieDian = [Table(QiDian_ind(i)).NextJieDian,ZhongDian_ind(i)]; Table(ZhongDian_ind(i)).NextJieDian = [Table(ZhongDian_ind(i)).NextJieDian,QiDian_ind(i)];endfor i = 1:size(all_data_3) Table(all_data_3(i)).PingTai = 1; % 是交巡警平台,则标记为1,否则不标记endfor i = 1:size(all_data_4_1) Table(all_data_4_1(i)).QuanShiQu_ChuRuKou = 1; % 是全市区出入口,则标记为1,否则不标记endfor i = 1:size(all_data_4_2) Table(all_data_4_2(i)).A_Qu_ChuRuKou = 1; % 是A区出入口,则标记为1,否则不标记end%---------------------------------
说明:①结构体 的 详细用法详见本文最后的 参考附录【6】📚 。
②代码里的结构体名为 “Table” ,其封装结果如下图所示。其中,“[ ]” 表示 “空” 。
第三步:绘制交通路线图(不含散点)
hold on;for i = 1:size(Table,2) if Table(i).QuYu == 'A' % 如果是 A 区,才执行下面的语句【注:我这里是用"1"来判断的】for j = 1:length(Table(i).NextJieDian)if 1 <= Table(i).NextJieDian(j) && Table(i).NextJieDian(j) <= 92 % 由 Excel附件一 可知,A区的数据点的编号范围为[1,92]cur_xx = [Table(i).X,Table(Table(i).NextJieDian(j)).X]; % 获取 起点和终点 的两个数据点的横坐标next_yy = [Table(i).Y,Table(Table(i).NextJieDian(j)).Y];% 获取 起点和终点 的两个数据点的纵坐标plot(cur_xx,next_yy,'b-'); % 用蓝色(blue)的短线连接 起点和终点endendendend
说明:①这里的 plot()函数 的使用和我们往常使用的角度不一样。(这两行代码,查了很多资料,调了将近两个小时 🍋)
因为我画直线的时候是一根一根地并以离散的形式来连的【关键点】⭐️⭐️⭐️。
本文后面还会再强调一次这关键点。
运行结果如下:
整个图的大致雏形就出来了! 😲
第四步:筛选第一问所要用到的散点数据
p_ZuoBiao = []; % 交巡警平台的坐标矩阵: 第一列装 数据点的横坐标;第二列装 数据点的纵坐标A_c_ZuoBiao = [];% A区出入口的坐标矩阵: 第一列装 数据点的横坐标;第二列装 数据点的纵坐标A_j_ZuoBiao = [];% A区交通路口的坐标矩阵:第一列装 数据点的横坐标;第二列装 数据点的纵坐标for i = 1:size(Table,2) if Table(i).QuYu == 'A'% 如果是 A 区,才执行下面的语句【注:我这里是用"1"来判断的】 if Table(i).PingTai == 1 % 如果该数据点是 A区的交巡警平台p_ZuoBiao = [ p_ZuoBiao ; [Table(i).X,Table(i).Y] ];end if Table(i).A_Qu_ChuRuKou == 1 % 如果该数据点是 A区的城区出入口A_c_ZuoBiao = [ A_c_ZuoBiao ; [Table(i).X,Table(i).Y] ];else% 否则该数据点就是 A区的交通路口A_j_ZuoBiao = [ A_j_ZuoBiao ; [Table(i).X,Table(i).Y] ];end endend
三个散点矩阵的数据如下:
第五步:集中绘制散点图
scatter(p_ZuoBiao(:,1),p_ZuoBiao(:,2),60,'ks'); scatter(A_c_ZuoBiao(:,1),A_c_ZuoBiao(:,2),20,'MarkerEdgeColor','b','MarkerFaceColor','r');scatter(A_j_ZuoBiao(:,1),A_j_ZuoBiao(:,2),10,'filled','b');legend('A区交巡警平台','出入A区的路口','A区的交通路口');
运行结果如下:
为什么会出现这么多 “data1、data2、…” 的标签呢?❔ ❔ ❔
因为我们画直线的时候是一根一根地并以离散的形式来连的【关键点】⭐️⭐️⭐️。
第六步:细节优化→图例修整、坐标说明+标题
①图例修整
操作步骤 分3步,如下图所示:🐾 🐾 🐾
🐟 🐟 🐟 🐟 🐟 🐟 🐟 🐟 🐟
✈️ ✈️ ✈️ ✈️ ✈️ ✈️ ✈️ ✈️ ✈️
🚁 🚁 🚁 🚁 🚁 🚁 🚁 🚁 🚁
②坐标说明+标题
.
整张图就完成啦 !😲 😲 😲
瞧瞧最终的成果图吧!😲 😲 😲
四、总结:
第一步:读取所有数据
第二步:将数据包装入结构体
第三步:绘制交通路线图(不含散点)
第四步:筛选第一问所要用到的散点数据
第五步:集中绘制散点图
第六步:细节优化→图例修整、坐标说明+标题
①图例修整
②坐标说明+标题
最后,我没有详细地阐述其原理,只阐述了有什么用、怎么用。详细原理可以参考本文最后的参考附录📚 📚 📚。
五、完整源码(/5/3补充)
因为评论区在.5.3之前的很多评论 表示无法实现理想效果,故笔者将其源码重新拼接+完善,并贴出如下:
【数据在文章最后的 参考附录[7] 📘。放在与代码同一目录文件夹即可】
感谢大家对问题的指出!
clcclearclose allclc,clear,close all;[all_data_1,QY] = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',1,'A2:E583'); % 附件1的数据all_data_2 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',2,'A2:B929'); % 附件2的数据all_data_3 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',3,'B2:B81'); % 附件3的数据all_data_4_1 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',4,'B2:B18'); % 附件4的数据all_data_4_2 = xlsread('cumcmB附件2_全市六区交通网路和平台设置的数据表.xls',4,'C2:C14'); % 附件4的数据ind = all_data_1(:,1);% 数据点的编号zuo_x = all_data_1(:,2); % 数据点的横坐标zuo_y = all_data_1(:,3); % 数据点的纵坐标QuYu = QY;% 数据点所在的区域【一共有A、B、...、F七个区域】FaAnLv = all_data_1(:,5); % 数据点的发案率QiDian_ind = all_data_2(:,1);% 交通道路的起点编号ZhongDian_ind = all_data_2(:,2); % 交通道路的终点编号% 第一种添加结构体成员的方法t = 1; % 用 t 来记录结构体的序号for i = 1:size(ind)% Table(t) = struct('ind',ind(i),'ZuoBiao',[zuo_x,zuo_y],'QuYu',QuYu(i),'FaAnLv',FaAnLv(i));Table(t) = struct('ind',ind(i),'X',zuo_x(i),'Y',zuo_y(i),'QuYu',QuYu(i),'FaAnLv',FaAnLv(i));t = t + 1;end%---------------------------------% 第二种添加结构体成员的方法---------for i = 1:size(ind)Table(i).NextJieDian = []; % 先初始化endfor i = 1:size(all_data_2,1) % 遍历每条边,然后把 起点 和 终点 连起来【双边都要连】Table(QiDian_ind(i)).NextJieDian = [Table(QiDian_ind(i)).NextJieDian,ZhongDian_ind(i)]; Table(ZhongDian_ind(i)).NextJieDian = [Table(ZhongDian_ind(i)).NextJieDian,QiDian_ind(i)];endfor i = 1:size(all_data_3) Table(all_data_3(i)).PingTai = 1; % 是交巡警平台,则标记为1,否则不标记endfor i = 1:size(all_data_4_1) Table(all_data_4_1(i)).QuanShiQu_ChuRuKou = 1; % 是全市区出入口,则标记为1,否则不标记endfor i = 1:size(all_data_4_2) Table(all_data_4_2(i)).A_Qu_ChuRuKou = 1; % 是A区出入口,则标记为1,否则不标记end%---------------------------------%---------获取坐标------------------------p_ZuoBiao = []; % 交巡警平台的坐标矩阵: 第一列装 数据点的横坐标;第二列装 数据点的纵坐标A_c_ZuoBiao = [];% A区出入口的坐标矩阵: 第一列装 数据点的横坐标;第二列装 数据点的纵坐标A_j_ZuoBiao = [];% A区交通路口的坐标矩阵:第一列装 数据点的横坐标;第二列装 数据点的纵坐标for i = 1:size(Table,2) if Table(i).QuYu == 'A'% 如果是 A 区,才执行下面的语句【注:我这里是用"1"来判断的】 if Table(i).PingTai == 1 % 如果该数据点是 A区的交巡警平台p_ZuoBiao = [ p_ZuoBiao ; [Table(i).X,Table(i).Y] ];end if Table(i).A_Qu_ChuRuKou == 1 % 如果该数据点是 A区的城区出入口A_c_ZuoBiao = [ A_c_ZuoBiao ; [Table(i).X,Table(i).Y] ];else% 否则该数据点就是 A区的交通路口A_j_ZuoBiao = [ A_j_ZuoBiao ; [Table(i).X,Table(i).Y] ];end endend%----------------------------------------%---------先画散点------------------------figure(1);hold on;scatter(p_ZuoBiao(:,1),p_ZuoBiao(:,2),60,'ks'); scatter(A_c_ZuoBiao(:,1),A_c_ZuoBiao(:,2),20,'MarkerEdgeColor','b','MarkerFaceColor','r');scatter(A_j_ZuoBiao(:,1),A_j_ZuoBiao(:,2),10,'filled','b');legend('A区交巡警平台','出入A区的路口','A区的交通路口');%----------------------------------------%---------再画连线------------------------for i = 1:size(Table,2) if Table(i).QuYu == 'A' % 如果是 A 区,才执行下面的语句【注:我这里是用"1"来判断的】for j = 1:length(Table(i).NextJieDian)if 1 <= Table(i).NextJieDian(j) && Table(i).NextJieDian(j) <= 92 % 由 Excel附件一 可知,A区的数据点的编号范围为[1,92]cur_xx = [Table(i).X,Table(Table(i).NextJieDian(j)).X]; % 获取 起点和终点 的两个数据点的横坐标next_yy = [Table(i).Y,Table(Table(i).NextJieDian(j)).Y];% 获取 起点和终点 的两个数据点的纵坐标plot(cur_xx,next_yy,'b-'); % 用蓝色(blue)的短线连接 起点和终点endendendend%----------------------------------------%---------重画一遍散点(更好看)---------------scatter(p_ZuoBiao(:,1),p_ZuoBiao(:,2),60,'ks'); scatter(A_c_ZuoBiao(:,1),A_c_ZuoBiao(:,2),20,'MarkerEdgeColor','b','MarkerFaceColor','r');scatter(A_j_ZuoBiao(:,1),A_j_ZuoBiao(:,2),10,'filled','b');legend('A区交巡警平台','出入A区的路口','A区的交通路口');%------------------------------------------
六、参考附录:
[1]《MATLAB中scatter函数的用法(绘制散点图)》
这里面有关于 scatter 的详细用法总结
链接: /xuxinrk/article/details/80212221.
[2]《MATLAB中关于scatter用法的官方文档》
和参考附录[1]类似,但肯定 官方原版的说明书 更好
链接: /help/matlab/ref/scatter.html#btrli6p-1.
[3]《matlab绘制X,Y二维散点图并标出序号》
需要在散点图上标序号时可以参考这篇
链接: /qq_29596177/article/details/53284364?utm_source=blogxgwz1.
[4]《用matlab画散点图,并指定点与点之间的连线》
如果作的散点图是稀疏矩阵,可以参考这篇,学用gplot()函数
链接: /heavenmark/article/details/82794488.
[5]《MATLAB中关于xlsread用法的官方文档》
链接: /help/matlab/ref/xlsread.html?searchHighlight=xlsread&s_tid=srchtitle.
[6]《MATLAB中关于struct用法的官方文档》
链接: /help/matlab/ref/struct.html?searchHighlight=struct&s_tid=srchtitle.
[7]《高教社杯全国大学生数学建模竞赛赛题 B题 数据》
链接: http://www./html_cn/node/a1ffc4c5587c8a6f96eacefb8dbcc34e.html.
数学建模系列文章——总结篇:《数模美一国一退役选手的经验分享[纪念版]》.
码字 码图不易,多多支持~ ❤️🙈🙈
感谢大家对问题的指出!(特别感谢对于.5.3之前的评论主)⭐️⭐️