0
votes

Good afternoon.

I am writing a SAS program that will loop through several sets of time-series/ observations. For each set, there is one observation per month, with roughly 450 observations/months total. For simplicity's sake, the months start at 1 and move sequentially.

Now, for each set of observations I have an additional set of variables to be employed. I am importing an auxiliary data set that contains these variables for all of the sets, and using the &&var&i. structure to assign each observation's variables a unique macro variable to be called during the execution of the main loop. So, for example, all of the variables in the first observation have a "1" concatenated onto their variable name, second observation variables have a "2," and so on. When the main loop goes through it's first iteration and calls &&var&i., it will resolve to &var1 and pull in the value assigned from the first observation in the auxiliary data set. I have tested this, and it is working fine.

Important note: each observation in the auxiliary set has a series of variables called ratio_1, ratio_2, ... up to ratio_9. After passing through the macro assignment above, they would assume macro names of ratio_11, ratio_21... for the first set, and ratio_12, ratio_22,... and so on for subsequent sets.

My problem arises when I try to insert code that is only supposed to occur at very specific time intervals within each set. Each set has a variable initial_check that determines on which month this code should begin executing. This code should then execute on each observation that occurs in 12-month increments. So, for example, set 1 might have an initial_check value of 36, meaning that the code will only execute for the observation on month 35 (see code below), with subsequent executions on months 47, 59, 71, and so on.

The first line of code is meant to determine that the code that follows only executes at the aforementioned intervals (the rem_var checks for the remainder of the difference between the current month and the initial_check, over 12 - if there is no remainder, then a multiple of 12 months has passed) :

if mon >= %eval(&&initial_check&k -1) and rem_var = 0 and mon < &&term&k. then do ;

I have run that code in isolation to check that each of its parameters is doing what it should, and it appears to be working correctly. The following code comes next:

** Iterate ratios ** 
if mon = %eval(&&initial_check&k. -1) then call symput('j',1) ;
else if mon = %eval(&&initial_check&k. +11) then call symput('j',2) ;
else if mon = %eval(&&initial_check&k. +23) then call symput('j',3) ;
else if mon = %eval(&&initial_check&k. +35) then call symput('j',4) ;
else if mon = %eval(&&initial_check&k. +47) then call symput('j',5) ;
else if mon = %eval(&&initial_check&k. +59) then call symput('j',6) ;
else if mon = %eval(&&initial_check&k. +71) then call symput('j',7) ;
else if mon = %eval(&&initial_check&k. +83) then call symput('j',8) ;
else if mon = %eval(&&initial_check&k. +95) then call symput('j',9) ;
end ;

Again, I have tested this using non-macro language (that is, assigning the values to regular variable j), and this also appears to be working. Unfortunately, even with the "mprint" option on, I can't see if the macro variable is being properly assigned. Following that, I have additional code that is only supposed to execute if that first condition was met.

if &&ratio_&j&k ne 0 then do ;

And HERE is the issue: I'm getting a note that macro variable j is unresolved. This code is only supposed to execute in an instance in which &j has been defined, so I can't figure out why it is unresolved. That &&ratio_&j&k is supposed to resolve to &ratio_11 in month 35, &ratio_21 in month 47, and so on for the first loop of the broader program.

I have tried experimenting with the macro versions of the conditional logic (%IF, %THEN, %DO), but have so far failed to get the results I want.

Would anyone happen to have any insight? I'm at my wit's end. I will be following this thread, so I can add details where necessary. And thank you in advance for taking the time to read this.

1
Is your if &&ratio_&j&k ne 0 then do ; statement in the same data step as the call symput that creates &j? If so, it won't work because &j will try to resolve during data step compile time, before the macro variable has been created.Quentin
In fact it is. The '&&ratio_&j&k' line follows the 'end' line directly. Would you suggest starting a different data step?Tacos_Tacos_Tacos
It would be helpful to see a small example data step, perhaps based on sashelp.class, to see exactly what you're doing in its entirety here. I suspect you have a combination of a misunderstanding of data step vs macro code, and a timing issue, but it's hard to tell with only bits of code here and there. The example should be something I can run on my machine, not dependent on your data - and doesn't need a bunch of lines like above, just two or three if conditions are fine to show the idea.Joe
If you are combining datasets why are you using macro variables instead of regular dataset variables?Tom
@Tom I would point you to NESUG 2009 (the "using a control dataset" section) for an explanation of what is happening with the auxiliary data set.Tacos_Tacos_Tacos

1 Answers

0
votes

We need more information. You cannot include the last two blocks of code in the same data step since the data step will use the value of the macro variable J that exists when the data step is compiled and not the one generated by the call symput() function.

Why isn't J just a data step variable?

If it is a macro variable and you want to use the value that call symput() created then you need to use symget() (or symgetn()) to retrieve it at run time. You can then use its value to generate the name of the macro variable that you actually want to reference.

if symgetn(cats('ratio_',symgetn('j'),"&k")) ne 0 then do ;