I have a scenario as follows:
data have;
input id var1 var2;
datalines;
1 . 5
2 3 4
3 4 5
5 0 6
6 9 8
;
run;
%let nvar = 2;
%let v1 = 5; /*Condition for var1*/
%let v2 = 8; /*Condition for var2*/
When i run this array , i am getting error.
data want;
set have;
array var{2} var1 : var&nvar;
array flag{2} flag1-flag&nvar;
do i = 1 to 2;
if var{i} >= 5 then flag{i} = 1;
else flag{i} = 0;
end;
drop i;
run;
This above code run correct but what i need is that instead of var{i} >= 5 i have to replace by var{i} >= &v{i} so i make
the condition to change as i changes.
However this modification does not work ,saying it can not resolve &v{i}.
Any suggestion ?
Thank you.
Hi @sascode , v1, v2 is not an array but just two macrovariables. If you want to keep them as macrovariables, one way to achieve your goal might be using a macro in your second data step:
data want; set have; array var{2} var1 : var&nvar; array flag{2} flag1-flag&nvar; %macro steps; %do i = 1 %to 2; if var{&i} >= &&v&i then flag{&i} = 1; else flag{&i} = 0; %end; %mend; %steps; run;
Hi @sascode , v1, v2 is not an array but just two macrovariables. If you want to keep them as macrovariables, one way to achieve your goal might be using a macro in your second data step:
data want; set have; array var{2} var1 : var&nvar; array flag{2} flag1-flag&nvar; %macro steps; %do i = 1 %to 2; if var{&i} >= &&v&i then flag{&i} = 1; else flag{&i} = 0; %end; %mend; %steps; run;
another way might be to define v1 and v2 as (temporary) array:
data have; input id var1 var2; datalines; 1 . 5 2 3 4 3 4 5 5 0 6 6 9 8 ; run; %let nvar = 2; data want; set have; array v{2} _temporary_; v{1} = 5; v{2} = 8; array var{2} var1 : var&nvar; array flag{2} flag1-flag&nvar; do i = 1 to 2; if var{i} >= 5 then flag{i} = 1; else flag{i} = 0; end; drop i; run;
I suggest you put the cutoff values into an array. You can initialize the array by using a predefined set of values, as I have done below. I also used a direct assignment for the flag[i] variable, rather than use an IF-THEN statement.
%let nvar = 2;
/* conditions for each var */
%let cutoffVal = (5 8);
data want;
set have;
array var[&nvar] var:;
array cutoff[&nvar] &cutoffVal;
array flag[&nvar];
do i = 1 to &nvar;
flag[i] = (var[i] >= cutoff[i]);
end;
drop i;
run;
proc print;
run;
Let's simplify a little here and avoid conflicting instructions to the SAS compiler.
For example you have this statement:
array var{2} var1 : var&nvar;
I think you want the array named VAR to consist of the variables VAR1 and VAR2 . But the way you are listing the variable names is wrong. You asked for all variables that start with VAR1 and then added an additional variable named VAR2 to the list. If you want variables with numeric suffixes from VAR1 to VAR&nvar then use a hyphen and not a colon.
Note there is no need to both tell SAS the number of variables and also list the actual variable names.
If you list the variables then you don't need tell SAS the array dimension, it can count.
So either just list the variables. Or tell SAS the number of variables and let it use the array name as the base for a series of variable names. These two ways to define the array both define the same array with the same variables in it.
array var var1-var&nvar;
array var[&nvar];
You could use THREE arrays here. One for the variables being checked. One for the flag variables being created. And one for the list of boundary points.
This will work easiest if you have all of the values in one macro variable:
%let values=5 8;
%let nvar=%sysfunc(countw(&values,%str( )));
data want;
set have;
array var[&nvar];
array flag[&nvar];
array boundary[&nvar] _temporary_ (&values);
do index = 1 to &nvar;
flag[index] = var[index] >= boundary[index];
end;
drop index;
run;
If you really need to start with multiple macro variables instead of just one macro variable then you can use SYMGETN() to retrieve the appropriate macro variable based on the value of the data step index variable. So there is no need to define the third array. Instead just set the flag variable this way:
flag[index] = var[index] >= symgetn(cats('v',index));
@sascode wrote:
Hi Tom, what you are saying is true based on the way i brought the probelm here. In my real situation , i had to tell sas the var names in the array because that dataset contains other vars which will be not part of this array.
I appreciate your help.
That makes NO sense at all. SAS will NOT add random variables into an array. Only the variables you list
array xx varA VarB some_other_var;
array yy yy1-yy200;
or the ones you imply.
array yy [100] ;
Well actually using the : modifier in your variable list, like in your posted code, can make the set of variables included depend on the variables that already exist when the ARRAY statement is compiled. In that case you can use the DIM() function to find the number of variables that ended up being included in the array.
array var var: ;
do index=1 to dim(var);
....
end;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.