【Matlab】绘制雷达图及Legend灵活控制

1. 绘制雷达图

本文根据:MATLAB 雷达图画图函数 修改,对于原文作者表示感谢。

function Draw_radar(data,lim,labels)
%data是要画图的数据(根据数据的个数来确定雷达图的轴数)
%lim是各指标画图上下限范围
%labels是坐标轴名称
    n=length(data);%维度
    adj_data=zeros(n,1);
    point=zeros(n,2);
    
    set(gca,'units','normal','pos',[0 0 1 1]);
    axis off
    axis equal
    hold on
    theta_last=pi/2;
    for i=1:n
        theta=2*pi/n*i+pi/2;
        plot([0,500*cos(theta)],[0,500*sin(theta)],'k-','linewidth',2);
        for j=1:5
           plot([j*100*cos(theta_last),j*100*cos(theta)],[j*100*sin(theta_last),j*100*sin(theta)],'--','linewidth',0.75,'color',[0.5,0.5,0.5]);
        end
        
        theta_last=theta;
        if data(i)<lim(i,1)
            adj_data(i)=0;
        elseif data(i)>lim(i,2)
            adj_data(i)=500;
        else
            adj_data(i)=(data(i)-lim(i,1))/(lim(i,2)-lim(i,1))*500;
        end
        point(i,1:2)=[adj_data(i)*cos(theta);adj_data(i)*sin(theta)];
        text_around(510*cos(theta),510*sin(theta),labels{i},theta);
    end
    
    for i=1:n
        theta=2*pi/n*i+pi/2;
        for j=1:5
            text_around(j*100*cos(theta),j*100*sin(theta),num2str(lim(i,1)+(lim(i,2)-lim(i,1))/5*j),theta+pi/2,7);
        end
    end
    plot([point(:,1);point(1,1)],[point(:,2);point(1,2)],'k-','linewidth',0.8);
    fill(point(:,1),point(:,2),[0.9 0.9 0.7])
    alpha(0.5);
    texts=findobj(gca,'Type','Text');
    minx=-300;
    maxx=300;
    miny=-300;
    maxy=300;
    for i=1:length(texts)
        rect=get(texts(i),'Extent');
        x=rect(1);
        y=rect(2);
        dx=rect(3);
        dy=rect(4);
        if x<minx
            minx=x;
        elseif x+dx>maxx
            maxx=x+dx;
        end
        if y<miny
            miny=y;
        elseif y+dy>maxy
            maxy=y+dy;
        end
    end
    axis([minx-50,maxx+50,miny-20,maxy+20]);
end

function text_around(x,y,txt,theta,fontsize)
    if nargin==4
        fontsize=10;
    end
    section=mod(theta+pi/12,2*pi);
    if section>pi+pi/6
        %上对齐
        if section>1.5*pi+pi/6
            %左对齐
            text(x,y,txt,'VerticalAlignment','cap','HorizontalAlignment','left','Fontsize',fontsize);
        elseif section>1.5*pi
            %中对齐
            text(x,y,txt,'VerticalAlignment','cap','HorizontalAlignment','center','Fontsize',fontsize);
        else
            %右对齐
            text(x,y,txt,'VerticalAlignment','cap','HorizontalAlignment','right','Fontsize',fontsize);
        end
    elseif section>pi
        %中、右对齐
        text(x,y,txt,'VerticalAlignment','middle','HorizontalAlignment','right','Fontsize',fontsize);
    elseif section>pi/6
        %下对齐
        if section>0.5*pi+pi/6
            %右对齐
            text(x,y,txt,'VerticalAlignment','bottom','HorizontalAlignment','right','Fontsize',fontsize);
        elseif section>0.5*pi
            %中对齐
            text(x,y,txt,'VerticalAlignment','bottom','HorizontalAlignment','center','Fontsize',fontsize);
        else
            %左对齐
            text(x,y,txt,'VerticalAlignment','bottom','HorizontalAlignment','left','Fontsize',fontsize);
        end
    else
        %中、左对齐
        text(x,y,txt,'VerticalAlignment','middle','HorizontalAlignment','left','Fontsize',fontsize);
    end
end

1.1 单数据雷达图

data = [5 8 1 4];
lim = [0,10;0,10;0,10;0,10];
labels = {'1','2','3','4'};
Draw_radar(data,lim,labels);

1.2 多数据雷达图 

当数据有多组时,例如:data = [5,8,1,4;7,5,4,8]。

可以绘制[5 8 1 4]之后,再hold on,最后绘制[7,5,4,8]即可。

data = [5 8 1 4];
lim = [0,10;0,10;0,10;0,10];
labels = {'1','2','3','4'};
Draw_radar(data,lim,labels);
hold on;
data = [7,5,4,8];
lim = [0,10;0,10;0,10;0,10];
labels = {'1','2','3','4'};
Draw_radar(data,lim,labels);

当然,最好把上面的操作封装一下,使用起来更方便,封装函数Draw_radar2代码如下: 

function Draw_radar2(data,lim,labels)
    hold on;
    for i=1:size(data,1)
        Draw_radar(data(i,:),lim,labels);
    end
end

2. legend自由控制

当你想显示legend时,上述的方法可能就会出现如下的效果。

解决方案详情可参考:http://blog.sciencenet.cn/blog-662112-764543.html,笔者从中受到启示,得出下面的解决方案:

通过设置IconDisplayStyle属性为false,通知Matlab不显示该plot语句所绘制图形的legend。

set(get(get(plot句柄,'Annotation'),'LegendInformation'),'IconDisplayStyle','off');

例如:如果只想显示第1,6,11,16,21条线的legend,则可以【伪代码】: 

for i = [2:5 7:10 12:15 17:20 22:25]                 
    set(get(get(H(i),'Annotation'),'LegendInformation'),'IconDisplayStyle','off');  
end 
legend('1','6','11','16','21');

其中,H为所有plot函数的句柄。

另外,调试发现,Draw_radar代码中的第39行,即最后一个plot绘图指令,就是我们要显示legend的线。对于上面的四个维度的数据,虚线一共4*5=20条,坐标轴实线共有4条,那么,第25条曲线就是我们需要显示legend的线。

 那么,我们就可以做点什么了。我们可以只设置最后一个plot绘图对象的IconDisplayStyle属性为on,其余均设置为false的方式,实现只显示第最后一条直线的legend的目的。

我们这里对最开始的Draw_radar函数做以下的修改:

  1. 首先,在Draw_radar函数中保存所有plot函数的句柄到数组H中;
  2. 接着,为了更能区分不同的曲线,笔者,将线的颜色和类型linestyle作为参数传入到Draw_radar函数中,当linestyle为'r-'时,对应的数据会显示为红色线型;
  3. 最后,为了更加清晰,将原有的填充中间区域注释掉了。

下面是修改后的Draw_radar和Draw_radar2的完整代码。 

function [H] = Draw_radar(data,lim,labels,linestyle)
%data是要画图的数据(根据数据的个数来确定雷达图的轴数)
%lim是各指标画图上下限范围
%labels是坐标轴名称
    H={};
    n=length(data);%维度
    adj_data=zeros(n,1);
    point=zeros(n,2);
    
    set(gca,'units','normal','pos',[0 0 1 1]);
    axis off
    axis equal
    hold on
    theta_last=pi/2;
    for i=1:n
        theta=2*pi/n*i+pi/2;
        H{length(H) + 1} = plot([0,500*cos(theta)],[0,500*sin(theta)],'k-','linewidth',2);
        for j=1:5
           H{length(H) + 1} = plot([j*100*cos(theta_last),j*100*cos(theta)],[j*100*sin(theta_last),j*100*sin(theta)],'--','linewidth',0.75,'color',[0.5,0.5,0.5]);
        end
        
        theta_last=theta;
        if data(i)<lim(i,1)
            adj_data(i)=0;
        elseif data(i)>lim(i,2)
            adj_data(i)=500;
        else
            adj_data(i)=(data(i)-lim(i,1))/(lim(i,2)-lim(i,1))*500;
        end
        point(i,1:2)=[adj_data(i)*cos(theta);adj_data(i)*sin(theta)];
        text_around(510*cos(theta),510*sin(theta),labels{i},theta);
    end
    
    for i=1:n
        theta=2*pi/n*i+pi/2;
        for j=1:5
            text_around(j*100*cos(theta),j*100*sin(theta),num2str(lim(i,1)+(lim(i,2)-lim(i,1))/5*j),theta+pi/2,7);
        end
    end
    H{length(H) + 1} = plot([point(:,1);point(1,1)],[point(:,2);point(1,2)],linestyle,'linewidth',1.5);%绘制
    %fill(point(:,1),point(:,2),[0.9 0.9 0.7])
    %alpha(0.5);
    texts=findobj(gca,'Type','Text');
    minx=-300;
    maxx=300;
    miny=-300;
    maxy=300;
    for i=1:length(texts)
        rect=get(texts(i),'Extent');
        x=rect(1);
        y=rect(2);
        dx=rect(3);
        dy=rect(4);
        if x<minx
            minx=x;
        elseif x+dx>maxx
            maxx=x+dx;
        end
        if y<miny
            miny=y;
        elseif y+dy>maxy
            maxy=y+dy;
        end
    end
    axis([minx-50,maxx+50,miny-20,maxy+20]);
end

function text_around(x,y,txt,theta,fontsize)
    if nargin==4
        fontsize=10;
    end
    section=mod(theta+pi/12,2*pi);
    if section>pi+pi/6
        %上对齐
        if section>1.5*pi+pi/6
            %左对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','cap','HorizontalAlignment','left','Fontsize',fontsize);
        elseif section>1.5*pi
            %中对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','cap','HorizontalAlignment','center','Fontsize',fontsize);
        else
            %右对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','cap','HorizontalAlignment','right','Fontsize',fontsize);
        end
    elseif section>pi
        %中、右对齐
        text(x,y,txt,'Interpreter','latex','VerticalAlignment','middle','HorizontalAlignment','right','Fontsize',fontsize);
    elseif section>pi/6
        %下对齐
        if section>0.5*pi+pi/6
            %右对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','bottom','HorizontalAlignment','right','Fontsize',fontsize);
        elseif section>0.5*pi
            %中对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','bottom','HorizontalAlignment','center','Fontsize',fontsize);
        else
            %左对齐
            text(x,y,txt,'Interpreter','latex','VerticalAlignment','bottom','HorizontalAlignment','left','Fontsize',fontsize);
        end
    else
        %中、左对齐
        text(x,y,txt,'Interpreter','latex','VerticalAlignment','middle','HorizontalAlignment','left','Fontsize',fontsize);
    end
end
function Draw_radar2(data,lim,labels,legendlabels)
    hold on;
    linestyles = {'k-','r-','b-','g-','c-','m-','y-'};
    for i=1:size(data,1)
        H = Draw_radar(data(i,:),lim,labels,linestyles{i});
        for j=1:length(H)-1
            set(get(get(H{j},'Annotation'),'LegendInformation'),'IconDisplayStyle','off');
        end
    end
    legend(legendlabels,'Interpreter','latex');
end

注意,这里的linestyle共有7种线型,如果要显示多于7组数据,加入新的线性即可。 调用方式如下:

lim = [0,40;0,50;0,20;0,10;0,200;];
labels = {'$$J_\alpha$$','$$J_\beta$$','$$J_\gamma$$','$$J_\delta$$','$$J_\epsilon$$'};
legendlabels = {'Plan 1','Plan 2','Plan 3'};
data = [25 32 11 7 151;
        33 45 11 6 151;
        28 12 11 9 162];
Draw_radar2(data,lim,labels,legendlabels);

### 使用 MATLAB 绘制雷达距离MATLAB绘制雷达距离可以通过 `polarplot` 函数实现。为了创建一个具有特定样式和颜色填充的雷达,准备数据并设置绘属性至关重要。 #### 数据准备 首先,准备好要展示的数据集。假设有一个包含多个观测值的数据矩阵,每一列代表不同的变量或维度。对于雷达来说,这些数据通常会被转换成极坐标形式以便于可视化[^1]。 ```matlab % 定义角度(以弧度为单位) angles = linspace(0, 2*pi, length(data)+1); angles(end) = []; % 去除最后一个重复点 % 将数据闭合形成封闭形 data = [data; data(1)]; angles = [angles; angles(1)]; figure; polarplot(angles, data, '-o'); title('Radar Distance Plot'); ``` 这段代码片段展示了如何定义角度范围以及使数据循环连接起来,从而确保表是一个完整的多边形而不是开放路径[^2]。 #### 设置表外观 为了让表更加直观易懂,还可以调整线条风格、标记符号以及其他视觉效果: - **填充颜色**: 可以为区域内部添加渐变色彩或其他类型的填充。 - **标签定制化**: 自定义轴上的文字描述使得表更易于理解。 下面的例子中加入了马卡龙色调作为背景填充,并设置了个性化的刻度标签[^3]: ```matlab hold on; fill(angles, data, 'm', 'FaceAlpha', 0.5); % 马卡龙紫色半透明填充 rticks([0 max(data)]); % 设定径向刻度 rticklabels({'Min Value','Max Value'}); % 更改径向刻度标签 thetaticks(linspace(0, 360, numel(labels)));% 修改角度间隔 thetaticklabels(labels); % 应用自定义角度标签 legend('Data Series'); % 添加例说明 grid minor % 显示次网格线 axis equal % 确保比例相同 hold off; ``` 此部分代码实现了对表细节的高度控制,包括但不限于颜色的选择、边界条件设定等操作[^4]。
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值