<?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 Array or Macro? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12133#M1301</link>
    <description>I need some advice on how best to process this problem.  I have a dataset of say 100,000 locations, with nonsequential IDs, a latitude and a longitude.  How would I best go about finding, for each ID, the closest location to it.  Don't worry about the actual calculation of distance, just wondering how best to process it.  I don't have any formal SAS training and I 've never used arrays, so any tips would be appreciated.  This is my current setup, it's certainly unwieldy, but I was rushed and didn't know how else to do it.  &lt;BR /&gt;
&lt;BR /&gt;
I created an observation number for sequencing called key and a macro variable obs to hold the total number of observations. Then I call a macro for each ID and its location.  The macro uses retain statements to keep track of the closest distance so far, and loops through until the last observation, then outputs 1 row.  So it's creating 100,000 1 row tables that I append together.  Seems ridiculous.  Thanks for your help.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%macro loop2;&lt;BR /&gt;
%do i = 1 %to &amp;amp;obs;&lt;BR /&gt;
	data _null_;&lt;BR /&gt;
		set locations;&lt;BR /&gt;
		where key = &amp;amp;i;&lt;BR /&gt;
		call symput ('ID', ID);&lt;BR /&gt;
		call symput ('lat', latitude);&lt;BR /&gt;
		call symput ('long', longitude);&lt;BR /&gt;
	run;&lt;BR /&gt;
	%loop(&amp;amp;ID, &amp;amp;lat, &amp;amp;long)&lt;BR /&gt;
%end;&lt;BR /&gt;
%mend;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%macro loop(ID_base, lat_base, long_base);&lt;BR /&gt;
data dist;&lt;BR /&gt;
set locations;&lt;BR /&gt;
keep ID_base closest_ID;&lt;BR /&gt;
retain closest_dist closest_ID;&lt;BR /&gt;
&lt;BR /&gt;
ID_base = "&amp;amp;ID_base";&lt;BR /&gt;
lat_base = &amp;amp;lat_base / 1000000;&lt;BR /&gt;
long_base = &amp;amp;long_base / -1000000;&lt;BR /&gt;
&lt;BR /&gt;
if ID ne ID_base then do;&lt;BR /&gt;
	currest_dist = ....;&lt;BR /&gt;
end;&lt;BR /&gt;
&lt;BR /&gt;
if current_dist &amp;lt; closest_dist or closest_dist = . then do;&lt;BR /&gt;
   closest_dist = current_dist;&lt;BR /&gt;
   closest_ID = ID;&lt;BR /&gt;
end;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
if key = &amp;amp;obs then output;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc append force data = dist base = dist_total;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
%mend;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%loop2;</description>
    <pubDate>Thu, 17 Feb 2011 17:40:52 GMT</pubDate>
    <dc:creator>buffheman</dc:creator>
    <dc:date>2011-02-17T17:40:52Z</dc:date>
    <item>
      <title>Array or Macro?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12133#M1301</link>
      <description>I need some advice on how best to process this problem.  I have a dataset of say 100,000 locations, with nonsequential IDs, a latitude and a longitude.  How would I best go about finding, for each ID, the closest location to it.  Don't worry about the actual calculation of distance, just wondering how best to process it.  I don't have any formal SAS training and I 've never used arrays, so any tips would be appreciated.  This is my current setup, it's certainly unwieldy, but I was rushed and didn't know how else to do it.  &lt;BR /&gt;
&lt;BR /&gt;
I created an observation number for sequencing called key and a macro variable obs to hold the total number of observations. Then I call a macro for each ID and its location.  The macro uses retain statements to keep track of the closest distance so far, and loops through until the last observation, then outputs 1 row.  So it's creating 100,000 1 row tables that I append together.  Seems ridiculous.  Thanks for your help.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%macro loop2;&lt;BR /&gt;
%do i = 1 %to &amp;amp;obs;&lt;BR /&gt;
	data _null_;&lt;BR /&gt;
		set locations;&lt;BR /&gt;
		where key = &amp;amp;i;&lt;BR /&gt;
		call symput ('ID', ID);&lt;BR /&gt;
		call symput ('lat', latitude);&lt;BR /&gt;
		call symput ('long', longitude);&lt;BR /&gt;
	run;&lt;BR /&gt;
	%loop(&amp;amp;ID, &amp;amp;lat, &amp;amp;long)&lt;BR /&gt;
%end;&lt;BR /&gt;
%mend;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%macro loop(ID_base, lat_base, long_base);&lt;BR /&gt;
data dist;&lt;BR /&gt;
set locations;&lt;BR /&gt;
keep ID_base closest_ID;&lt;BR /&gt;
retain closest_dist closest_ID;&lt;BR /&gt;
&lt;BR /&gt;
ID_base = "&amp;amp;ID_base";&lt;BR /&gt;
lat_base = &amp;amp;lat_base / 1000000;&lt;BR /&gt;
long_base = &amp;amp;long_base / -1000000;&lt;BR /&gt;
&lt;BR /&gt;
if ID ne ID_base then do;&lt;BR /&gt;
	currest_dist = ....;&lt;BR /&gt;
end;&lt;BR /&gt;
&lt;BR /&gt;
if current_dist &amp;lt; closest_dist or closest_dist = . then do;&lt;BR /&gt;
   closest_dist = current_dist;&lt;BR /&gt;
   closest_ID = ID;&lt;BR /&gt;
end;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
if key = &amp;amp;obs then output;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc append force data = dist base = dist_total;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
%mend;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
%loop2;</description>
      <pubDate>Thu, 17 Feb 2011 17:40:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12133#M1301</guid>
      <dc:creator>buffheman</dc:creator>
      <dc:date>2011-02-17T17:40:52Z</dc:date>
    </item>
    <item>
      <title>Re: Array or Macro?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12134#M1302</link>
      <description>You might find this paper useful [pre]http://www.nesug.org/Proceedings/nesug03/at/at008.pdf[/pre]I think the problem this paper discusses may be exactly what you are trying to do.&lt;BR /&gt;
&lt;BR /&gt;
There may be a SAS procedure that does, perhaps someone with more experience will know.</description>
      <pubDate>Thu, 17 Feb 2011 17:56:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12134#M1302</guid>
      <dc:creator>data_null__</dc:creator>
      <dc:date>2011-02-17T17:56:37Z</dc:date>
    </item>
    <item>
      <title>Re: Array or Macro?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12135#M1303</link>
      <description>Hi.&lt;BR /&gt;
In the documentation of proc sql .I found this code ,hope it will help you.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
[pre]&lt;BR /&gt;
proc sql outobs=10;&lt;BR /&gt;
title ’Neighboring Cities’;&lt;BR /&gt;
select a.City format=$10., a.State,&lt;BR /&gt;
 a.Latitude ’Lat’, a.Longitude ’Long’,&lt;BR /&gt;
 b.City format=$10., b.State,&lt;BR /&gt;
 b.Latitude ’Lat’, b.Longitude ’Long’,&lt;BR /&gt;
 sqrt(((b.latitude-a.latitude)**2) +&lt;BR /&gt;
 ((b.longitude-a.longitude)**2)) as dist format=6.1&lt;BR /&gt;
from sql.uscitycoords a, sql.uscitycoords b&lt;BR /&gt;
where a.city ne b.city and&lt;BR /&gt;
 calculated dist =&lt;BR /&gt;
 (select min(sqrt(((d.latitude-c.latitude)**2) +&lt;BR /&gt;
 ((d.longitude-c.longitude)**2)))&lt;BR /&gt;
   from sql.uscitycoords c, sql.uscitycoords d&lt;BR /&gt;
   where c.city = a.city and&lt;BR /&gt;
     c.state = a.state and&lt;BR /&gt;
        d.city ne c.city)&lt;BR /&gt;
order by a.city;&lt;BR /&gt;
[/pre]&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
And the best way to get answer is to post some your origin data and output you need.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
Ksharp

Message was edited by: Ksharp</description>
      <pubDate>Thu, 24 Feb 2011 06:55:04 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Array-or-Macro/m-p/12135#M1303</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2011-02-24T06:55:04Z</dc:date>
    </item>
  </channel>
</rss>

