MATLAB | 绘制scatter散点图时如何自动标注超范围散点?

本文来讲一下如何自动标注超出坐标区域范围的点,例如这样:

如图右侧的红叉代表横坐标超过范围的点的纵坐标
,当然下方的红叉代表纵坐标超过范围点的横坐标。

本文使用的自己编写的工具函数scatterOOR将被放在文末,先讲讲咋用哈,

基础使用

假设编写了如下绘制散点图的代码:

clc; clear; close all
rng(1)
% 生成随机点(Generate random points)
mu = [2 3; 6 7; 8 9];
S  = cat(3,[1 0; 0 2],[1 0; 0 2],[1 0; 0 1]);
r1 = abs(mvnrnd(mu(1,:),S(:,:,1),100));
r2 = abs(mvnrnd(mu(2,:),S(:,:,2),100));
r3 = abs(mvnrnd(mu(3,:),S(:,:,3),100));
% 绘制散点图(Draw scatter chart)
hold on
propCell = {
    
    'LineWidth',1.2,'MarkerEdgeColor',[.3,.3,.3],'SizeData',60};
scatter(r1(:,1),r1(:,2),'filled','CData',[0.40 0.76 0.60],propCell{
    
    :});
scatter(r2(:,1),r2(:,2),'filled','CData',[0.99 0.55 0.38],propCell{
    
    :});
scatter(r3(:,1),r3(:,2),'filled','CData',[0.55 0.63 0.80],propCell{
    
    :});
% 增添图例(Draw legend)
lgd = legend('scatter1','scatter2','scatter3');
lgd.Location = 'northwest';
lgd.FontSize = 14;
% 坐标区域基础修饰(Axes basic decoration)
ax=gca; grid on
ax.FontName   = 'Cambria';
ax.Color      = [0.9,0.9,0.9];
ax.Box        = 'off';
ax.TickDir    = 'out';
ax.GridColor  = [1 1 1];
ax.GridAlpha  = 1;
ax.LineWidth  = 1;
ax.XColor     = [0.2,0.2,0.2];
ax.YColor     = [0.2,0.2,0.2];
ax.TickLength = [0.015 0.025];
% 隐藏轴线(Hide XY-Ruler)
pause(1e-6)
ax.XRuler.Axle.LineStyle = 'none';
ax.YRuler.Axle.LineStyle = 'none';


ax.XLim = [-2,10];
ax.YLim = [2,14];

我们直接在代码最后加上一行:

scatterOOR()

或者

scatterOOR(gca)

即第一个参数是坐标区域对象,可省略。直接简单的调用就能达到下面的效果:

若是想要超出范围的点画的花哨点呢?可通过自定义scatter图形属性来实现,例如以下两种方法:

scatterOOR('filled','CData',[0,0,.8],'LineWidth',1.5,...
    'MarkerEdgeColor',[.5,.5,.5],'SizeData',120,'Marker','s')
scatterOOR(gca,'filled','CData',[0,0,.8],'LineWidth',1.5,...
    'MarkerEdgeColor',[.5,.5,.5],'SizeData',120,'Marker','s')

我们可以注意超出范围点默认图例名称为OOR,这个名称咋改呢?

也非常简单,例如将名称改为LALALA,可在代码最后加上这样两行:

OORHdl = findobj(ax,'Tag','SLANOOR');
OORHdl.DisplayName = 'LALALA';

工具函数完整代码

非常短哈只有不到40行:

function scatterOOR(ax,varargin)
% Copyright (c) 2023, Zhaoxu Liu / slandarer
if nargin < 1
    ax = gca;
end
if ~isa(ax,'matlab.graphics.axis.Axes')  
    varargin = [{
    
    ax}, varargin(:)'];
    ax = gca;
end
ax.NextPlot = 'add';
if isempty(varargin)
    varargin={
    
    'filled','CData',[.8,0,0],'LineWidth',1.5,...
    'MarkerEdgeColor',[.8,0,0],'SizeData',120,'Marker','x'};
end

OORHdl = findobj(ax,'Tag','SLANOOR');
if isempty(OORHdl)
    OORHdl = scatter([],[],varargin{
    
    :},'Tag','SLANOOR','DisplayName','OOR');
end
fullHdl = findobj(ax,'Type','scatter');
fullXData = [fullHdl(:).XData];
fullYData = [fullHdl(:).YData];

moveAxes();
addlistener(ax,'MarkedClean',@moveAxes);
    function moveAxes(~,~)
        tBool = fullXData >= ax.XLim(2) | fullXData <= ax.XLim(1)...
              | fullYData >= ax.YLim(2) | fullYData <= ax.YLim(1);
        tFullXData = fullXData; 
        tFullYData = fullYData;
        tFullXData(tFullXData >= ax.XLim(2)) = ax.XLim(2);
        tFullXData(tFullXData <= ax.XLim(1)) = ax.XLim(1);
        tFullYData(tFullYData >= ax.YLim(2)) = ax.YLim(2);
        tFullYData(tFullYData <= ax.YLim(1)) = ax.YLim(1);
        tFullXData = tFullXData(tBool);
        tFullYData = tFullYData(tBool);
        OORHdl.XData = tFullXData;
        OORHdl.YData = tFullYData;
    end
end

猜你喜欢

转载自blog.csdn.net/slandarer/article/details/131833062
今日推荐