I have about 80,000 coordinate pairs that I need to access Google Maps and get the driving distance and time for. The program then parses the resulting HTML code for the driving time and distance. It seems the problem might be that I have the latitude and longitude of pair 1 and latitude and longitude of pair 2 as individual numeric variables, and I'm trying to read them into a string variables of the form (lat1, long1) and (lat2, long2) so I can feed it to Google in the form it requires. I get several errors in my code that I can't seem to resolve. Any help is appreciated. My code is below.
The dataset variables lat and long are what I want to combine in the macro variable "lltract," and the variables lat_msa and long_msa I want to combine in the macro variable "llmsa."
* Data with coordinates; data tract_data; set dtmsa.tract_data; keep msaid year stateid countyid tractid lat long lat_msa long_msa; run; * Place number of tract coordinate pairs in a macro variable; proc sql noprint; select count(msaid) into :ncoords from tract_data; quit; * Create a macro that contains a loop to access Google Maps for every tract; %macro distance_time; * Delete any dataset named drivetime that might exist in the work library; proc datasets lib = work nolist; delete drivetime; quit; * Read one observation at a time from the dataset; %do j=1 %to &ncoords; data _null_; nrec = &j; set tract_data point=nrec; call symputx('lltract',catx(',',lat,long)); call symputx('llmsa', catx(',',lat_msa,long_msa)); stop; run; * Compile the URL for Google Maps; filename x url "http://maps.google.com/maps?daddr=&lltract.%nrstr(&saddr)=&llmsa"; data temp; retain lltract &lltract llmsa &llmsa; infile x lrecl=32000 pad; input; loc = find(_infile_,'dditd>'); if loc ne 0 then do; text = substr(_infile_,loc,50); text = scan(text,1,'&'); distance = input(scan(text,-1,'>'),comma12.); loc = find(_infile_,'about'); text = substr(_infile_,loc,50); text = scan(text,3,'<>'); * Convert time to seconds; select; * Combine days and hours; when (find(text,'day') ne 0) time = 86400*input(scan(text,1,' '),best.) + 3600*input(scan(text,3,' '),best.); * Combine hours and minutes; when (find(text,'hour') ne 0) time = 3600*input(scan(text,1,' '),best.) + 60*input(scan(text,3,' '),best.); * Just minutes; otherwise time = 60*input(scan(text,1,' '),best.); end; output; stop; end; keep lltract llmsa distance time; format time time.; run; filename x clear; * Add observation to the final dataset; proc append base = drivetime data=temp; run; %end; %mend; * Use the macro; %distance_time;
I'm getting the following errors for each coordinate pair.
NOTE: Line generated by the macro variable "LLTRACT".
1 32.386086,-99.758258
-
22
200
NOTE: Line generated by the macro variable "LLMSA".
1 32.401025,-99.811409
-
22
200
NOTE: Variable "text" was given a default length of 32767 as the result of a function call. If
you do not like this, please use a LENGTH statement to declare "text".
ERROR 22-322: Syntax error, expecting one of the following: a name, ;, _ALL_, _CHARACTER_,
_CHAR_, _NUMERIC_.
ERROR 200-322: The symbol is not recognized and will be ignored.
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.TEMP may be incomplete. When this step was stopped there were 0
observations and 4 variables.
WARNING: Data set WORK.TEMP was not replaced because this step was stopped.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
cpu time 0.03 seconds
NOTE: Fileref X has been deassigned.
NOTE: Appending WORK.TEMP to WORK.DRIVETIME.
NOTE: BASE data set does not exist. DATA file is being copied to BASE file.
NOTE: There were 0 observations read from the data set WORK.TEMP.
NOTE: The data set WORK.DRIVETIME has 0 observations and 9 variables.
NOTE: PROCEDURE APPEND used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds
please use a LENGTH statement to declare "text".
length text $24.;
your default length of 32767 sure does waste space.
So this statement in your macro probably does not make sense.
retain lltract &lltract llmsa &llmsa;
If the values of those macro variables are like that showed in the log.
NOTE: Line generated by the macro variable "LLTRACT". 1 32.386086,-99.758258 NOTE: Line generated by the macro variable "LLMSA". 1 32.401025,-99.811409
Might be clearer to you (and hence easier to get right) if you didn't use RETAIN. Since the values are in macro variables already then just use normal assignment statements to set the values. So what if SAS will reassign the value every iteration. It is not like your data step was changing the values.
lltract="&lltract";
llmsa="&llmsa";
Thanks for the great replies, but I'm still a little confused. Bear in mind this is my first attempt at a macro program, so I apologize in advance if my questions seems rudimentary.
Where would I insert the LENGTH statement and what code would I replace with lltract = &lltract and llmsa = &llmsa?
I actually looked quite a bit on the length statement, but couldn't find an example that clearly showed where to insert it into code similar to mine.
You need to have an idea what code you want to generate before you ask SAS to generate code for you.
Get the syntax working with hard coded values, like the ones in your error message.
The set the hard coded values into macro variables with %LET statements and replace the hard coded values with macro variable references. Get that to work.
Then wrap the rest of your logic around it where the macro variable values are being generated by code.
As to your question on LENGTH statement. You need to understand that a SAS data step will define the variables in the dataset it is generating based on how you first use them. (Note this includes SET or MERGE statement that references variables from existing datasets). So if you want to be certain how the variable will be defined the use a LENGTH (or ATTRIB) statement as the first place where the variable is referenced. So right after the DATA statement.
I put my length assignments as the first line/s of code in my data-steps.
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.