<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Function for choosing closest observation to a value in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448181#M283410</link>
    <description>&lt;P&gt;Example input data&lt;/P&gt;
&lt;P&gt;Example output data&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Instructions here: &lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-data-AKA-generate/ta-p/258712" target="_blank"&gt;https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-data-AKA-generate/ta-p/258712&lt;/A&gt; will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the {i} icon or attached as text to show exactly what you have and that we can test code against.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Are the variables you need "closest to A" character or numeric? (goes to how to select "closest")&amp;nbsp;If you have ties for "distance" between the values do you have a rule for selecting the lowest, largest or random between them? Do the three selected x, y and z&amp;nbsp;values have to be unique or may one repeat (some value on different observations)?&lt;/P&gt;</description>
    <pubDate>Fri, 23 Mar 2018 15:10:08 GMT</pubDate>
    <dc:creator>ballardw</dc:creator>
    <dc:date>2018-03-23T15:10:08Z</dc:date>
    <item>
      <title>Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448171#M283409</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I was wondering if there is a function in SAS to select the observation where the value of the variable is closest to value x within a certain group.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I am working with financial data, so for example, say i have company&amp;nbsp;YYYY&amp;nbsp;on 03/23/18. I may have 50+ observations within that group. I need to select three observations out of that group, where the value of variable A&amp;nbsp;is closest to x, y, and z. I am planning to put this code inside a macro so that is is easy to change around values of x, y, and z for various tests.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I would like for the output dataset to be all variables currently in my dataset but just those three observations for each company/date combination.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The only way I can think of is adding columns with the difference between x, y, z and the value of variable A and selecting the minimum. Is this really the most efficient way?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Please let me know if&amp;nbsp;anything is unclear and thank you in advance!&lt;/P&gt;</description>
      <pubDate>Fri, 23 Mar 2018 14:38:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448171#M283409</guid>
      <dc:creator>ag8711</dc:creator>
      <dc:date>2018-03-23T14:38:59Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448181#M283410</link>
      <description>&lt;P&gt;Example input data&lt;/P&gt;
&lt;P&gt;Example output data&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Instructions here: &lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-data-AKA-generate/ta-p/258712" target="_blank"&gt;https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-data-AKA-generate/ta-p/258712&lt;/A&gt; will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the {i} icon or attached as text to show exactly what you have and that we can test code against.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Are the variables you need "closest to A" character or numeric? (goes to how to select "closest")&amp;nbsp;If you have ties for "distance" between the values do you have a rule for selecting the lowest, largest or random between them? Do the three selected x, y and z&amp;nbsp;values have to be unique or may one repeat (some value on different observations)?&lt;/P&gt;</description>
      <pubDate>Fri, 23 Mar 2018 15:10:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448181#M283410</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2018-03-23T15:10:08Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448189#M283411</link>
      <description>&lt;P&gt;There are many definitions of distance. The results will depend on which you use.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For Euclidean distance, you can use the EUCLID function in the DATA step. Suppose that you want to find students whose (Age, Height, Weight) values are closest to the targets (13, 62, 100). You can compute the Euclidean distance as follows:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Closest;
/* target (Age, Height, Weight) = (13, 62, 100) */
set Sashelp.Class;
EuclidDist = Euclid(Age-13, Height-62, Weight-100);
run;

proc sort data=Closest;
by EuclidDist;
run;

proc print data=Closest(obs=3); /* 3 closest students */
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;For multivariate distances, the more reasonable choice of distance is &lt;A href="https://blogs.sas.com/content/iml/2012/02/15/what-is-mahalanobis-distance.html" target="_self"&gt;the Mahalanobis distance&lt;/A&gt;, which takes into account correlations between variables. &lt;A href="http://support.sas.com/kb/30/662.html" target="_self"&gt;There are several ways to compute the Mahalanobis distance in SAS/STAT software.&lt;/A&gt;&amp;nbsp;You can also use the MAHALANOBIS function in SAS/IML, as follows:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc iml;
use Sashelp.Class;
read all var _NUM_ into X[colname=VarNames];
read all var "Name";
close;

target = {13 62 100};
MD = Mahalanobis(X, target);
print MD X[c=VarNames];

call sortndx(idx, MD);
Y = MD[idx,] || X[idx,];
Y = Y[1:3, ]; /* only 3 closest */
print Y[colname=("Dist" || varNames) rowname=(Name[idx,])];
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 23 Mar 2018 15:20:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448189#M283411</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2018-03-23T15:20:54Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448247#M283412</link>
      <description>&lt;P&gt;You want to rank the 50 observations for the absolute difference of variable A against 3 specified values - i.e. 3 rankings.&amp;nbsp; And you want to keep the records for RANK1=1&amp;nbsp; (rank of A vs the first specified value), RANK2=1 and RANK3=1:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here an example using the IBM daily stock records in SASHELP.STOCKS, where the criterion variable is VOLUME:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data ibm_stocks;
  set sashelp.stocks;
  where stock='IBM';
run;

data need /view=need;
  set ibm_stocks;
  array dist {*} dist1-dist3;
  array values {3} _temporary_ (4700000,11600000,5500000);

  do i=1 to 3;
    dist{i}=abs(volume-values{i});
  end;
run;

proc rank data=need out=want (where=(rank1=1 or rank2=1 or rank3=1));
  var dist1 dist2 dist3;
  ranks rank1 rank2 rank3;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The data set NEED is a data set VIEW, not a data set FILE.&amp;nbsp; I.e. it is not processed until a subsequent step call for data set NEED.&amp;nbsp; As a result, its content is not written to disk, but rather streamed to the calling step&amp;nbsp; (the PROC RANK in this case).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have used specified volumes of 4,700,000;&amp;nbsp;&amp;nbsp; 11,600,000; and 5,500,000.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Of course, it's possible that one record could be closest to 2 (or more) target values.&amp;nbsp; But I assume you are unlikely to issue such targets.&lt;/P&gt;</description>
      <pubDate>Fri, 23 Mar 2018 17:29:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448247#M283412</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2018-03-23T17:29:29Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448396#M283413</link>
      <description>&lt;P&gt;I would start with something simple&amp;nbsp;like this, and come back here if it isn't efficient enough&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let x=90;
%let y=110;
%let z=125;

%let A=weight;

proc sql;
select *
from sashelp.class
group by sex
having 
    abs(&amp;amp;A-&amp;amp;x) = min(abs(&amp;amp;A-&amp;amp;x)) or 
    abs(&amp;amp;A-&amp;amp;y) = min(abs(&amp;amp;A-&amp;amp;y)) or 
    abs(&amp;amp;A-&amp;amp;z) = min(abs(&amp;amp;A-&amp;amp;z));
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;                    Name      Sex       Age    Height    Weight
                    -------------------------------------------
                    Judy      F          14      64.3        90
                    Mary      F          15      66.5       112
                    Janet     F          15      62.5     112.5
                    William   M          15      66.5       112
                    Thomas    M          11      57.5        85
                    Robert    M          12      64.8       128
&lt;/PRE&gt;</description>
      <pubDate>Sat, 24 Mar 2018 04:54:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448396#M283413</guid>
      <dc:creator>PGStats</dc:creator>
      <dc:date>2018-03-24T04:54:23Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448815#M283414</link>
      <description>&lt;P&gt;Thank you everyone, I really appreciate the help! I tried the simple SQL code and it worked well, I just need to refine my results a little bit more now that I'm seeing the output.&amp;nbsp;&lt;/P&gt;&lt;P&gt;this is the sql code that I ran from PG's answer:&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;%MACRO value(year=,mon=,a=,t=,d=,dataset=);&lt;BR /&gt;proc sql;&lt;BR /&gt;create table mylib.&amp;amp;dataset._&amp;amp;year as&lt;BR /&gt;select *&lt;BR /&gt;from mylib.master_&amp;amp;year&lt;BR /&gt;group by security_id, date,&amp;nbsp;mat&lt;BR /&gt;having&lt;BR /&gt;abs(&amp;amp;mon-&amp;amp;a) = min(abs(&amp;amp;mon-&amp;amp;a)) or&lt;BR /&gt;abs(&amp;amp;mon-&amp;amp;o) = min(abs(&amp;amp;mon-&amp;amp;o)) or&lt;BR /&gt;abs(&amp;amp;mon-&amp;amp;d) = min(abs(&amp;amp;mon-&amp;amp;d));&lt;BR /&gt;quit;&lt;BR /&gt;%MEND value;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;this is the dataset that I end up with:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data mylib.monvalues_2010;&lt;BR /&gt;infile datalines dsd truncover;&lt;BR /&gt;input date:DATE9. SECURITY_ID:32. c_vol:32. mat:32. p_vol:32. mon:32.;&lt;BR /&gt;datalines4;&lt;BR /&gt;04JAN2010,100892,,12,1.544622,0.5255413075&lt;BR /&gt;04JAN2010,100892,,12,0.602076,0.7988227875&lt;BR /&gt;04JAN2010,100892,0.301887,12,0.285932,1.0090393105&lt;BR /&gt;04JAN2010,100892,,47,0.749772,0.5255413075&lt;BR /&gt;04JAN2010,100892,0.351766,47,0.420842,0.7988227875&lt;BR /&gt;04JAN2010,100892,0.304283,47,0.30528,1.0090393105&lt;BR /&gt;04JAN2010,100892,0.383761,138,0.398305,0.7988227875&lt;BR /&gt;04JAN2010,100892,,138,0.524082,0.5255413075&lt;BR /&gt;04JAN2010,100892,0.322661,138,0.333717,1.0090393105&lt;BR /&gt;04JAN2010,100892,0.326735,229,0.336752,1.0090393105&lt;BR /&gt;04JAN2010,100892,0.362469,229,0.378213,0.8408660921&lt;BR /&gt;04JAN2010,100892,,229,0.494307,0.5255413075&lt;BR /&gt;04JAN2010,100892,,383,0.474313,0.5255413075&lt;BR /&gt;04JAN2010,100892,0.325869,383,0.338696,1.0510826151&lt;BR /&gt;04JAN2010,100892,0.367339,383,0.37962,0.8408660921&lt;BR /&gt;04JAN2010,100892,0.369302,747,0.394957,0.8408660921&lt;BR /&gt;04JAN2010,100892,0.38087,747,0.432982,0.6306495691&lt;BR /&gt;04JAN2010,100892,0.348698,747,0.361181,1.0510826151&lt;BR /&gt;05JAN2010,100892,,11,0.635303,0.7967313585&lt;BR /&gt;05JAN2010,100892,0.300998,11,0.301864,1.0010214505&lt;BR /&gt;05JAN2010,100892,,11,1.680322,0.5107252298&lt;BR /&gt;05JAN2010,100892,,46,0.786692,0.5107252298&lt;BR /&gt;05JAN2010,100892,,46,0.40056,0.7967313585&lt;BR /&gt;05JAN2010,100892,0.305781,46,0.309152,1.0010214505&lt;BR /&gt;05JAN2010,100892,0.321738,137,0.322548,1.0010214505&lt;BR /&gt;05JAN2010,100892,0.380163,137,0.391764,0.7967313585&lt;BR /&gt;05JAN2010,100892,,137,0.544914,0.5107252298&lt;BR /&gt;;;;;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In one of my macro scenarios i need to add keep the min observation within the interval. I can use an if-then macro but i'm not sure how to add it to this sql code. For the example values d=0.5, t=0.8, a=1, I need to choose the observations with the values closest to 1 and 0.8 but within [0.8,1], and the value closest to 0.5 but within [0.5, 1].&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Additionally, c_vol can't be missing for the&amp;nbsp;observation that is selected as the closest to a (but it definitely can be missing for the other values selected), so I need to select the closest to a with a value for c_vol. This doesn't come up in the first 25 obs above, but it does occur in the dataset.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 26 Mar 2018 21:24:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/448815#M283414</guid>
      <dc:creator>ag8711</dc:creator>
      <dc:date>2018-03-26T21:24:56Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/449184#M283415</link>
      <description>&lt;P&gt;This what your &lt;EM&gt;scenario&lt;/EM&gt; would translate to&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
create table mylib.&amp;amp;dataset._&amp;amp;year as

select *
from mylib.master_&amp;amp;year
where &amp;amp;mon between &amp;amp;t and &amp;amp;a
group by security_id, date, mat
having 
    &amp;amp;mon = min(&amp;amp;mon) or 
    &amp;amp;mon = max(&amp;amp;mon) 

union

select *
from mylib.master_&amp;amp;year
where c_vol is not missing and &amp;amp;mon between &amp;amp;d and &amp;amp;a
group by security_id, date, mat
having &amp;amp;mon = max(&amp;amp;mon);
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;(untested)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Suggestion -&amp;nbsp;Test each&amp;nbsp;&lt;EM&gt;scenario&lt;/EM&gt; with a small example data set and experiment.&lt;/P&gt;</description>
      <pubDate>Tue, 27 Mar 2018 22:42:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/449184#M283415</guid>
      <dc:creator>PGStats</dc:creator>
      <dc:date>2018-03-27T22:42:17Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/449737#M283416</link>
      <description>&lt;P&gt;For a discussion of various definitions of distances and how to compute each in SAS, see&lt;A href="https://blogs.sas.com/content/iml/2018/03/28/closest-observation-target-value.html" target="_self"&gt; "Find the distances between observations and a target value"&lt;/A&gt;.&lt;/P&gt;</description>
      <pubDate>Thu, 29 Mar 2018 18:38:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/449737#M283416</guid>
      <dc:creator>Rick_SAS</dc:creator>
      <dc:date>2018-03-29T18:38:33Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/699748#M283417</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13684"&gt;@Rick_SAS&lt;/a&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;What if i know the age (For ex 24) and I just want to keep the max height row for every subject.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 18 Nov 2020 12:10:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/699748#M283417</guid>
      <dc:creator>bharath86</dc:creator>
      <dc:date>2020-11-18T12:10:26Z</dc:date>
    </item>
    <item>
      <title>Re: Function for choosing closest observation to a value</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/699757#M283418</link>
      <description>&lt;P&gt;Please state your question in a new thread of your own. Supply example data in usable form, and show the expected outcome.&lt;/P&gt;
&lt;P&gt;Also tell where the conceptual difference is to this:&amp;nbsp;&lt;A href="https://communities.sas.com/t5/Statistical-Procedures/Assign-category-to-max-age-below-24Months/m-p/698547" target="_blank" rel="noopener"&gt;https://communities.sas.com/t5/Statistical-Procedures/Assign-category-to-max-age-below-24Months/m-p/698547&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 18 Nov 2020 12:21:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Function-for-choosing-closest-observation-to-a-value/m-p/699757#M283418</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2020-11-18T12:21:34Z</dc:date>
    </item>
  </channel>
</rss>

