Home > FMAToolbox > General > Match.m

Match

PURPOSE ^

Match - Replace values in one list with closest values in a second list.

SYNOPSIS ^

function [matched,only1,only2] = Match(list1,list2,varargin)

DESCRIPTION ^

Match - Replace values in one list with closest values in a second list.

  USAGE

    [matched,only1,only2] = Match(list1,list2,<options>)

    list1          first list
    list2          second list
    <options>      optional list of property-value pairs (see table below)

    =========================================================================
     Properties    Values
    -------------------------------------------------------------------------
     'match'       optional matching criterion: 'up', 'down' (default) or
                   'closest' (see below)
     'error'       matched values for which the difference exceeds this
                   threshold are set to NaN (default = inf)
    =========================================================================

  OUTPUT

    matched        values in list2 that matched those of list1
    only1          elements in list1 that were not matched by any element in list2
    only2          elements in list2 that did not match any element in list1

    only1 and only2 are lists of logical indices.

  NOTE

    Pairs are matched in the following way. Assume the lists are sorted in
    ascending order and let list1 = [a(1)...a(n)] and list2 = [b(1)...b(m)].
    We are trying to match each a(i) with one of the b(1..m). Suppose

       b(1) <= ... <= b(j) <= a(i) <= b(j+1) <= ... <= b(m)

    Then a(i) will be matched with either b(j) or b(j+1), depending on the
    'match' option:

       1) 'down' (default) => b(j)
       2) 'up' => b(j+1)
       3) 'closest' => the one that minimizes the distance
          (b(j) if the distances are equal)

    If however the distance between a(i) and b(j) (or b(j+1)) is too large
    (see option 'error'), then none of the b(1..m) matches a(i).

    Note that this function is generally asymmetrical.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [matched,only1,only2] = Match(list1,list2,varargin)
0002 
0003 %Match - Replace values in one list with closest values in a second list.
0004 %
0005 %  USAGE
0006 %
0007 %    [matched,only1,only2] = Match(list1,list2,<options>)
0008 %
0009 %    list1          first list
0010 %    list2          second list
0011 %    <options>      optional list of property-value pairs (see table below)
0012 %
0013 %    =========================================================================
0014 %     Properties    Values
0015 %    -------------------------------------------------------------------------
0016 %     'match'       optional matching criterion: 'up', 'down' (default) or
0017 %                   'closest' (see below)
0018 %     'error'       matched values for which the difference exceeds this
0019 %                   threshold are set to NaN (default = inf)
0020 %    =========================================================================
0021 %
0022 %  OUTPUT
0023 %
0024 %    matched        values in list2 that matched those of list1
0025 %    only1          elements in list1 that were not matched by any element in list2
0026 %    only2          elements in list2 that did not match any element in list1
0027 %
0028 %    only1 and only2 are lists of logical indices.
0029 %
0030 %  NOTE
0031 %
0032 %    Pairs are matched in the following way. Assume the lists are sorted in
0033 %    ascending order and let list1 = [a(1)...a(n)] and list2 = [b(1)...b(m)].
0034 %    We are trying to match each a(i) with one of the b(1..m). Suppose
0035 %
0036 %       b(1) <= ... <= b(j) <= a(i) <= b(j+1) <= ... <= b(m)
0037 %
0038 %    Then a(i) will be matched with either b(j) or b(j+1), depending on the
0039 %    'match' option:
0040 %
0041 %       1) 'down' (default) => b(j)
0042 %       2) 'up' => b(j+1)
0043 %       3) 'closest' => the one that minimizes the distance
0044 %          (b(j) if the distances are equal)
0045 %
0046 %    If however the distance between a(i) and b(j) (or b(j+1)) is too large
0047 %    (see option 'error'), then none of the b(1..m) matches a(i).
0048 %
0049 %    Note that this function is generally asymmetrical.
0050 
0051 % Copyright (C) 2004-2012 by Michaƫl Zugaro
0052 %
0053 % This program is free software; you can redistribute it and/or modify
0054 % it under the terms of the GNU General Public License as published by
0055 % the Free Software Foundation; either version 3 of the License, or
0056 % (at your option) any later version.
0057 
0058 % Default values
0059 match = 'down';
0060 err = inf;
0061 
0062 % Check parameters
0063 if nargin < 2 | mod(length(varargin),2) ~= 0,
0064   error('Incorrect number of parameters (type ''help <a href="matlab:help Match">Match</a>'' for details).');
0065 end
0066 if ~isdvector(list1) | ~isdvector(list2),
0067     error('Incorrect sizes: ''list1'' and ''list2'' must be vectors (type ''help <a href="matlab:help Match">Match</a>'' for details).');
0068 end
0069 
0070 % Parse parameter list
0071 for i = 1:2:length(varargin),
0072   if ~isa(varargin{i},'char'),
0073     error(['Parameter ' num2str(i+2) ' is not a property (type ''help <a href="matlab:help Match">Match</a>'' for details).']);
0074   end
0075   switch(lower(varargin{i})),
0076 
0077     case 'match',
0078         match = lower(varargin{i+1});
0079         if ~isastring(match,'up','down','closest'),
0080             error('Incorrect value for property ''match'' (type ''help <a href="matlab:help Match">Match</a>'' for details).');
0081       end
0082 
0083     case 'error',
0084         err = varargin{i+1};
0085         if ~isdscalar(err,'>=0'),
0086             error('Incorrect value for property ''error'' (type ''help <a href="matlab:help Match">Match</a>'' for details).');
0087         end
0088 
0089     otherwise,
0090       error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help <a href="matlab:help Match">Match</a>'' for details).']);
0091 
0092   end
0093 end
0094 
0095 % Sort elements in both list so that list1 = [a1 a2 a3 ... an] and list2 = [b1 b2 b3 ... bm]
0096 [list1,idx1] = sort(list1(:));
0097 [list2,idx2] = sort(list2(:));
0098 
0099 % Find 'up' and 'down' matching indices
0100 % (We need both, because this will allow us to compare matches if the criterion is 'closest')
0101 n = length(list2);
0102 up = MatchUpIndices(list1,list2);
0103 down = up-1;
0104 
0105 % List corresponding values in list2
0106 % Special cases: when matching down (resp. up), values in list1 lesser (resp. greater)
0107 % than all values in list2 cannot be matched; set them to NaN
0108 goodUp = up>0 & up<=n;
0109 matchedUp = nan(size(up));
0110 matchedUp(goodUp) = list2(up(goodUp));
0111 goodDown = down>0 & down<=n;
0112 matchedDown = nan(size(down));
0113 matchedDown(goodDown) = list2(down(goodDown));
0114 
0115 % Use match criterion
0116 switch(match),
0117     case 'up',
0118         matched = matchedUp;
0119     case 'down',
0120         matched = matchedDown;
0121     case 'closest',
0122         [~,idx] = min(abs([matchedUp matchedDown]-[list1 list1]),[],2);
0123         matched = matchedUp;
0124         matched(idx==2) = matchedDown(idx==2);
0125 end
0126 
0127 % Check error threshold
0128 bad = abs(matched-list1) > err+eps; % eps is to compensate for inevitable numerical rounding errors such as 1.1-1.0>0.1
0129 matched(bad) = nan;
0130 
0131 % Output
0132 only1 = isnan(matched);
0133 matched = matched(~only1);
0134 only1(idx1) = only1;
0135 only2 = logical(zeros(size(list2)));
0136 m = unique(matched);
0137 [~,i] = setdiff(list2,m);
0138 only2(i) = 1;
0139 only2(idx2) = only2;
0140

Generated on Fri 16-Mar-2018 13:00:20 by m2html © 2005