打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Matlab数据可视化(2):基础篇 II

五. 添加图例

(源代码legends.m)
在图像包含较多图形时,适当的图例对快速、正确的理解图像反映的信息是必不可少的。以下一个实例可以说明精心设计图例的重要性。
我们在一幅图像中,同时绘出10个不同均值和方差的正态分布曲线。数据可以由如下代码生成,或直接加载10NormalDistributions.mat
  1. % stdVect and meanVect  
  2. stdVect = [.49,.26,.93,.47,.25,.43,.7,.4,.18,.86];  
  3. meanVect = [-.8,-.62,-.44,-.27,-.09,.09,.27,.44,.62,.8];  
  4.   
  5. % 正态分布数据,每行一个  
  6. t = -1:.02:1;  
  7. dataVect = ones(10,length(t));  
  8. for i=1:10  
  9.     dataVect(i,:) = (1/sqrt(2*pi)/stdVect(i))*...  
  10.         exp(-(t-meanVect(i)).^2/(2*stdVect(i)^2));       
  11. end  
  12.   
  13. % 图例说明  
  14. legendMatrix = cell(1,10);  
  15. for i = 1:10      
  16.     legendMatrix{i} = [sprintf( 'mean = %.2f, std = %.2f',...  
  17.         meanVect(i),stdVect(i) )];  
  18. end  
  19. legend(legendMatrix);  
  20.   
  21. save('10NormalDistribution.mat', 'stdVect','meanVect',...  
  22.     'dataVect','legendMatrix');  
  23.   
  24. clear;  
1、首先,我们不加额外处理的使用图例。(图1)显然,这幅图的可读性非常差,我们很难将参数和图形对应起来,有的曲线颜色甚至还相同!
  1. % 加载数据 meanVect stdVect legendMatrix  
  2. load 10NormalDistributions;  
  3.   
  4. % 绘图  
  5. plot(dataVect');  
  6. xlim([0,100]);  
  7.   
  8. % 添加标注  
  9. title({'10种不同的正态分布','图例不缺乏清晰度','颜色区分也不明显!'},'Color',[1 0 0]);  
  10. xlabel('x');  
  11. ylabel('x的概率密度函数');  
图1
2、我们通过改变曲线的颜色(color)、线型(line style)和标志(marker)的方式增加可读性,并将图例放置在图像外边。(图2)
  1. % 为不同曲线生成不同的设置  
  2. LineStyles = {'-','--',':'};  
  3. MarkerSpecs = {'+','o'};  
  4. ColorSpecs = {'r','g','b','k'};  
  5. cnt = 1;  
  6. for i = 1:length(LineStyles)  
  7.     for j = 1:length(MarkerSpecs)  
  8.         for k = 1:length(ColorSpecs)  
  9.             LineSpecs{cnt} = [LineStyles{i} MarkerSpecs{j} ...  
  10.                 ColorSpecs{k}];  
  11.             cnt = cnt+1;  
  12.         end  
  13.     end  
  14. end  
  15.   
  16. figure; hold on;  
  17. for i = 1:10      
  18.     plot(dataVect(i,:), LineSpecs{i});      
  19. end  
  20. xlim([0 100]);  
  21.   
  22. title({'10种不同的正态分布','使用不同的颜色和线型','可读性大大提高'});  
  23. xlabel('x'); ylabel('x的概率密度函数');  
  24. legend(legendMatrix,'Location','NorthEastOutside',...  
  25.     'Fontsize',8);  
  26. box on;  

图2

3、 有时候,我们可能会将图形分组。由于每执行一次绘图任务,legend的计数就会增加1,因此,在这种情况下,我们可以通过如下方式来减少图例数量。(图3)
  1. % 合并图例  
  2. figure; hold;  
  3. h1 = plot(dataVect(1:6,:)','rd-','Color',[1 0 0]);  
  4. h2 = plot(dataVect(7:10,:)','k*--','Color',[0 0 0]);  
  5. xlim([0 100]);  
  6.   
  7. h = legend([h1(1),h2(1)],['Color 1' char(10) 'first 6 curves'],...  
  8.     ['Color 2' char(10) 'remaining 4 curves'],...  
  9.     'Location','Best');  
  10.   
  11. % 提高可读性,将图例字体颜色调整为与图形颜色一致  
  12. % 注意:每两个为一组,分别代表直线、标号和文字的颜色的属性,且顺序与所表示的图形顺序相反,即第一个绘制的图形的图例出现在数组的最后3个  
  13. c = get(h,'Children');  
  14. set(c(1:3),'Color',[0,0,0]);  
  15. set(c(4:6),'Color',[1,0,0]);  
图3
4、利用legendlex优化图例。(图4)
legendfex为我们提供了更加灵活的调整图例格式的功能。得用legendflex, 我们不但可以调整说明的布局(指定分几行或几列显示),还可以单独调整图标和文字的大小,设定图例相对于任何对象的位置(原始legend限于坐标轴)。利用 legendflex ,我们还可以为图例添加小标题。legendflex可从之里下载
  1. figure('units','normalized','position',...  
  2.     [ 0.4172 0.1769 0.3 0.5]);  
  3. hold on;  
  4. for i = 1:10  
  5.     h(i) = plot(dataVect(i,:), LineSpecs{i});  
  6. end  
  7. xlim([0 100]);  
  8. legendflex(h,... %handle to plot lines  
  9.     legendMatrix,... %corresponding legend entries  
  10.     'ref', gcf, ... %which figure  
  11.     'anchor', {'nw','nw'}, ... %location of legend box  
  12.     'buffer',[30 -5], ... %an offset wrt the location  
  13.     'nrow',4, ... %number of rows  
  14.     'fontsize',8,... %font size  
  15.     'xscale',.5); %a scale factor for actual symbols  
  16.   
  17. title({'应用legendflex优化图像显示','可以调整相对位置、布局,字体及图标大小'});  
  18. xlabel('x'); ylabel('x的概率密度函数');  



图4

六. 通过数据变换突出细节特征

(源代码trans.m)
有些数据通过一定的变换后,更便于可视化,也更容易发现隐藏的信息。
1、绘制一幅双Y轴图(图5)
  1. %% 生成数据  
  2. x = 1:50;  
  3. r = 5e5;  
  4. E = [ones(1,30) linspace(1,0,15) zeros(1,5)];  
  5. y1 = r * (1+E).^x;  
  6.   
  7. %% 绘制又Y轴图形  
  8. y2 = log(y1);  
  9. axes('position',[0.1300    0.1100    0.7750    0.7805]);  
  10.   
  11. [AX,H1,H2] = plotyy(x,y1,x,y2,'plot');  
  12. title({'利用对数变换增强数据','增长、稳定、衰减的可视化效果'});  
  13. set(get(AX(1),'Ylabel'),'String','data');  
  14. set(get(AX(2),'Ylabel'),'String','log(data)');  
  15. xlabel('x'); set(H1,'LineStyle','--'); set(H2,'LineStyle',':');  
  16.   
  17. %% 添加标注  
  18. annotation('textarrow',[.26 .28],[.67,.37],'String',['指数增长' char(10) '(1到30周期)']);  
  19. annotation('textarrow',[.7 .7],[.8,.64],'String',['非指数衰减' char(10) '(30到45周期)']);  
  20. annotation('textarrow',[.809 .859],[.669,.192],'String',['稳定' char(10) '(45到50周期)']);  
  21. legend({'原始数据','对数变换后的数据'},'Location','Best');  
  22. set(gcf,'Paperpositionmode','auto','Color',[1 1 1]);  
图5
2、在数字较大时,matlab会默认采用科学计数法,有时这可能不是我们想要的,我们可以通过如下方式处理。(图6)
  1. %% 关闭科学记数法格式  
  2. % 改变图像大小  
  3. set(gcf,'units','normalized','position',[0.0411    0.5157    0.7510    0.3889]);  
  4. % AX(1) 存储的是原始数据的句柄  
  5. title({'利用对数变换增强数据','增长、稳定、衰减的可视化效果','关闭科学计数法格式'});  
  6. n=get(AX(1),'Ytick');  
  7. set(AX(1),'yticklabel',sprintf('%d |',n'));  



图6

3、通过缩放坐标轴达到变换的目的
上边实例中,我们通过对原始数据进行取对数操作达到变换的效果。由于对数操作的常用性,Matlab允许我们直接对X和Y轴进行对数缩放。semilogx、semilogy、loglog可以分别对X轴、Y轴和XY轴进行对数缩放。这也可以通过设置坐标轴的xscale和yscale属性实现。
  1. %% 直接利用 semilogx, semilogy, loglog  
  2. figure;  
  3. subplot(2,1,1);  
  4. semilogy(x,y1);  
  5. xlabel('x');   
  6. ylabel('取对数后数据');  
  7. title({'MATLAB的semilogy函数',...  
  8.                '直接将Y轴对数缩放后显示'});  
  9. subplot(2,1,2);  
  10. plot(x,y1);   
  11. set(gca,'yscale','log');  
  12. xlabel('x');   
  13. ylabel('取对数后的数据');  
  14. title({'使用常规的plot进行绘图','然后通过理性属性达到相同目的'});  

图7

七. 多图的绘制

(源代码subfig.m)
1、常规子图的绘制
我们利用苹果公司2011年度每日股票交易数据为例,绘制包括开盘价、最高价、最低价、收盘价、成交量和临近收盘价在内的6个趋势图。

首先加载数据
  1. %% 加载数据并按时间先后顺序排列  
  2. [AAPL dateAAPL] = xlsread('AAPL_090784_012412.csv');  
  3. dateAAPL = datenum({dateAAPL{2:end,1}});  
  4. dateAAPL = dateAAPL(end:-1:1);  
  5. AAPL = AAPL(end:-1:1,:);  
  6. % 选择时间窗口(2011年全年)  
  7. rangeMIN = datenum('1/1/2011');  
  8. rangeMAX = datenum('12/31/2011');  
  9. idx = find(dateAAPL >= rangeMIN & dateAAPL <= rangeMAX);  
然后,通过subplot命令绘图(图8)
  1. %% 使用subplot绘图命令绘制常规子图网格  
  2. % 注意设置各个子图的标题内容的title命令的位置   
  3.   
  4. figure('units','normalized','position',[ 0.0609    0.0593    0.5844    0.8463]);  
  5. matNames = {'开盘价','最高价','最低价','收盘价','成交量','临近收盘价'};  
  6. for i = 1:6  
  7.     subplot(3,2,i);   
  8.     plot(idx,AAPL(idx,i));  
  9.     if i~=5  
  10.         title([matNames{i} ' $, subplot(3,2,' num2str(i) ')'],'Fontsize',12,'Color',[1 0 0 ]);      
  11.         ylabel('美元');  
  12.     else  
  13.         title([matNames{i} ' vol, subplot(3,2,' num2str(i) ')'],'Fontsize',12,'Color',[1 0 0 ]);  
  14.         ylabel('成交量');  
  15.     end  
  16.     set(gca,'xtick',linspace(idx(1),idx(end),12),'xticklabel',...  
  17.         datestr(linspace(dateAAPL(idx(1)),dateAAPL(idx(end)),12),...  
  18.                                                 'mm'),'Fontsize',10,'fontweight','bold');  
  19.     rotateXLabels(gca,40);  
  20.     box on; axis tight  
  21. end  
  22. % 添加总标题  
  23. annotation('textbox',[ 0.37   0.96   0.48   0.03],'String','2011年度苹果公司股价趋势','Fontsize',14,'Linestyle','none');  
图8
2、进阶篇
我们可以自定义子图的布局,并且子图可以是任何一种图形。下面我们绘制包括3个垂直排列的子图(由上而下编号1、2、3)的图像(如图9)。子图1展示选定时间窗口内的股价走势,子图2展示相同时期内的成交量,子图3则显示全部时间内股价的变化情况。

图9
子图1是一个面积图,可通过area命令绘制。
  1. %% 自定义子图布局  
  2. figure('units','normalized','Position',[ 0.0427    0.2102    0.6026    0.6944]);  
  3.   
  4. %% 子图1显示收盘价随时间的变化趋势  
  5. % 设置坐标轴位置  
  6. Panel1 = axes('Position',[ 0.0570    0.5520    0.8850    0.3730]);hold;   
  7. % 绘制面积图   
  8. area(AAPL(idx,4),'FaceColor',[188 210 238]/255,'edgecolor',[54 100 139 ]/255);   
  9. % 设置坐标轴相关参数  
  10. xlim([1 length(idx)]);   
  11. yminv = min(AAPL(idx,4))-.5*range(AAPL(idx,4));  
  12. ymaxv = max(AAPL(idx,4))+.1*range(AAPL(idx,4));  
  13. ylim([yminv ymaxv]);  
  14. box on;  
  15. % 绘制网格线  
  16. set(gca,'Ticklength',[0 0],'YAxisLocation','right');  
  17. line([linspace(1,length(idx),15);linspace(1,length(idx),15)],[yminv*ones(1,15); ymaxv*ones(1,15)],'Color',[.9 .9 .9]);  
  18. line([ones(1,10); length(idx)*ones(1,10)],[linspace(yminv, ymaxv,10); linspace(yminv, ymaxv,10);],'Color',[.9 .9 .9]);  
  19. % 设置注解  
  20. set(gca,'xtick',linspace(1,length(idx),10),'xticklabel',datestr(linspace(dateAAPL(idx(1)),dateAAPL(idx(end)),10),'ddmmmyy'));  
  21. title({'苹果公司股票价格,','(选定时间窗口内细节展示)'},'Fontsize',12);  
子图2是一个条形图,可通过bar命令绘制。
  1. %% 子图2展示相同时间段内成交量的变化情况  
  2. % 设置坐标轴位置  
  3. Panel2 = axes('Position',[ 0.0570 0.2947  0.8850  0.1880]);  
  4. % 用条形图绘图  
  5. bar(1:length(idx), AAPL(idx,5),.25,...  
  6.                      'FaceColor',[54 100 139 ]/255);   
  7. hold; xlim([1 length(idx)]);hold on;  
  8. % 添加网格线  
  9. yminv = 0;  
  10. ymaxv = round(max(AAPL(idx,5)));  
  11. line([linspace(1,length(idx),30);...  
  12.       linspace(1,length(idx),30)],...  
  13.      [yminv*ones(1,30); ymaxv*ones(1,30)],...  
  14.                             'Color',[.9 .9 .9]);  
  15. line([ones(1,5); length(idx)*ones(1,5)],...  
  16.      [linspace(yminv, ymaxv,5); ...  
  17.       linspace(yminv, ymaxv,5);],'Color',[.9 .9 .9]);  
  18. ylim([yminv ymaxv]);  
  19. % 设置特殊的时间刻度  
  20. set(gca, 'Ticklength',[0 0],...  
  21. 'xtick',linspace(1,length(idx),10),'xticklabel',...  
  22.   datestr(linspace(dateAAPL(idx(1)),dateAAPL(idx(end)),10),...  
  23.                                                 'ddmmmyy'));  
  24. tickpos = get(Panel2,'ytick')/1000000;  
  25. for i = 1:numel(tickpos)  
  26.     C{i} = [num2str(tickpos(i)) 'M'];   
  27. end  
  28. set(Panel2,'yticklabel',C,'YAxisLocation','right');  
  29. text(0,1.15*ymaxv,'成交量','VerticalAlignment','top',...  
  30.         'Color',[54 100 139 ]/255,'Fontweight','bold');  

子图3是也一个面积图,其中选定时间段被高亮,这是通过在大图上叠加绘制一个与子图1相同颜色的小得到。
  1. %% 子图3展示全部时间段内股价变化情况,其中被选中的时间窗口高亮显示  
  2. Panel3 = axes('Position',[0.0570    0.1100    0.8850    0.1273]);  
  3. area(dateAAPL, AAPL(:,4),'FaceColor',[234 234 234 ]/255,'edgecolor',[.8 .8 .8]); hold;   
  4. line([min(idx) min(idx)],get(gca,'ylim'),'Color','k');  
  5. line([max(idx) max(idx)],get(gca,'ylim'),'Color','k');  
  6. set(gca,'Ticklength',[0 0]);  
  7. % 相同颜色重新绘制时间窗口内的趋势  
  8. area(dateAAPL(idx),AAPL(idx,4),'FaceColor',[188 210 238]/255,'edgecolor',[54 100 139 ]/255);   
  9. ylim([min(AAPL(:,4)) 1.1*max(AAPL(:,4))]);  
  10. xlabel('长期股价走势');  
  11. line([min(get(gca,'xlim')) min(get(gca,'xlim'))],get(gca,'ylim'),'Color',[1 1 1]);  
  12. line([max(get(gca,'xlim')) max(get(gca,'xlim'))],get(gca,'ylim'),'Color',[1 1 1]);  
  13. line(get(gca,'xlim'),[max(get(gca,'ylim')) max(get(gca,'ylim'))],'Color',[1 1 1]);  
  14. line(get(gca,'xlim'),[min(get(gca,'ylim')) min(get(gca,'ylim'))],'Color',[1 1 1]);  
  15. set(gca,'xticklabel',datestr(get(gca,'xtick'),'yyyy'),'yticklabel',[]);  

八. 可视化直观地比较实验结果

(源代码comparison.m)
这涉及多种方法的对比实验中,选择适当的方式进行可视化分析,有助于我们快速、直观地对各种方法的优劣进行评判。我们以五种聚类算法在5个测试集上的实验结果为数据,通过绘图对其进行比较。
我们已经知道,matlab自带有多种配色方案(colormap)可供选择,我们还可以自定义配色方案。为了保证配色的友好性和易区分性,我们可以通过在线工具color brewer(http://colorbrewer2.org/),对配色进行测试,辅助我们找到比较好的方案。

图10
  1. %% 定义可视化方案   
  2. % 设定图像大小和位置  
  3. figure('units','normalized','Position',[ 0.0880    0.1028    0.6000    0.6352]);  
  4.   
  5. % 绘制一个隐藏的坐标轴,其X轴刻度标签列出进行比较的五种算法的名称  
  6. hh = axes('Position',[.1,.135,.8,.1]);  
  7. set(gca,'Visible','Off','TickLength',[0.0 0.0],'TickDir','out','YTickLabel','','xlim',[0 nosOfMethods],'FontSize',11,'FontWeight','bold');  
  8. set(gca,'XTick',.5:nosOfMethods-.5,'XTickLabel',{'K Means','Fuzzy C Means','Hierarchical','Maximize Expectation','Dendogram'});  
  9. catgeoryLabels = {'Fresh Tissue','FFPE','Blood','DNA','Simulated'};  
  10. rotateXLabels(gca,20);  
  11. % 将Y轴长等分为五份,分别分配给5个测试集结果  
  12. y = linspace(.142,.75,nosOfCategories);  
  13.   
  14. % Place an axes for creating each row dedicated to a sample   
  15. % category. The height of the axes corresponds to the total   
  16. % number of samples in that category.  
  17. %    
  18. for i = 1 :nosOfCategories  
  19.       
  20.     if CategoryTotals(i); ylimup = CategoryTotals(i); else ylimup = 1; end  
  21.     dat = [MethodPerformanceNumbers(i,:)];  
  22.     h(i) = axes('Position',[.1,y(i),.8,y(2)-y(1)]);  
  23.     set(gca,'XTickLabel','','TickLength',[0.0 0.0],'TickDir','out','YTickLabel','','xlim',[.5 nosOfMethods+.5],'ylim',[0 ylimup]);  
  24.   
  25.     % Use the line command to create bars representing the number of successes   
  26.     % in each category using colour scheme defined at the beginning of this recipe  
  27.     line([1:nosOfMethods; 1:nosOfMethods],[zeros(1,nosOfMethods); dat],'Color',Colors(i,:),'Linewidth',7);box on;  
  28.       
  29.     % Place the actual number as a text next to the bar  
  30.     for j= 1:nosOfMethods  
  31.         if dat(j); text(j+.01,dat(j)-.3*dat(j),num2str(dat(j)),'Rotation',20,'FontSize',13); end  
  32.     end  
  33.       
  34.     % Add the category label  
  35.     ylabel([catgeoryLabels{i} char(10) '#Samples' char(10) ' = ' num2str(ylimup) ],'Fontsize',11);   
  36. end  
  37. % Add annotations  
  38. title('5种聚类算法成功的次数','Fontsize',14,'Fontweight','bold');  
  39. axes(h(3));  
  40. text(-0.02,-80,'聚类算法在不同数据集上的表现','rotation',90,'Fontsize',14,'Fontweight','bold');  


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
EXCEL图表格式设置详解
Excel图表:旋风图的制作方法
美化图表有诀窍,给你6个小技巧
Excel制表后如何旋转?
EXCEL完成两组相差甚远的数据的显示
有效标记图表
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服