MATLAB | How to automatically label out-of-range scatter points when drawing a scatter plot?

This article will talk about how to automatically label points beyond the range of the coordinate area, for example:

The red cross on the right side of the figure represents the ordinate of the point whose abscissa exceeds the range
, and of course the red cross below represents the abscissa of the point whose ordinate exceeds the range.

The self-written tool functions used in this article scatterOORwill be placed at the end of the article. Let me talk about how to use them first.

basic use

Suppose you write the following code to draw a scatterplot:

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];

We directly add a line at the end of the code:

scatterOOR()

or

scatterOOR(gca)

That is, the first parameter is the coordinate area object, which can be omitted. Direct and simple calls can achieve the following effects:

What about fancy dots for stippling that's out of bounds? It can be realized by customizing scattergraphic properties, such as the following two methods:

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')

We can notice that the default legend name of the out-of-range point is OOR, how to change this name?

It is also very simple. For example, to change the name to LALALA, you can add these two lines at the end of the code:

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

Tool function complete code

Very short, less than 40 lines:

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

Guess you like

Origin blog.csdn.net/slandarer/article/details/131833062