Error in simple SAS macro - macros

I am testing the macro loop. The code is simple but always come the error message "Macro function %SCAN has too many arguments". Could not understand the reason. Anyone could explain it? Thanks!
The code is:
%macro test;
proc sql;select distinct tj, max(tj) into: tp separated by ",", : maxtp from ASA_k where tj>0;quit;
%do i=1 %to &maxtp.;
%let timep=%scan(&tp.,&i.,",");
%put &timep.;
%end;
%mend;
%test;

In macro-varriable, you store values separated by commas, these commas are problematic. You need to mask them after resolving a macro-variable, using %bquote macro-function. Also your third parameter in %scan function is not right, because your separator are , and ". You have to just mask comma using %str macro-function. Just like that:
%macro test;
proc sql;
select distinct tj, max(tj)
into :tp separated by ",", :maxtp
from ASA_k
where tj>0;
quit;
%do i=1 %to &maxtp.;
%let timep=%scan(%bquote(&tp.),&i.,%str(,));
%put &timep.;
%end;
%mend;
%test;

Related

SAS Select Into Dynamic Naming

I am trying to use SAS proc sql select into for 8 different scenarios.
%MACRO Loop();
proc sql;
%do i=1 %to 8;
select total_value
into :Sol_&i. separated by ','
from Master.adjusted_hours
where Solicitation = "&i.";
%end;
quit;
%mend;
%Loop();
However when I use the %put function, the macro variable isn't recognized. The error is "Apparent symbolic reference SOL_1 not resolved."
%put &Sol_1;
How can I store the value in this macro variable and call it later in the code?
You need to declare SOL_1 SOL_2, etc as global macro variables. I wasn't sure what was in your data, so I created some dummy data.
%global SOL_1 SOL_2 SOL_3 SOL_4 SOL_5 SOL_6 SOL_7 SOL_8;
data adjusted_hours;
do x = 1 to 8;
solicitation=put(x, 1.);
do total_value = 1 to 10;
output;
end;
end;
drop x;
run;
%MACRO Loop();
proc sql noprint;
%do i = 1 %to 8;
select total_value
into : Sol_&i. separated by ','
from adjusted_hours
where Solicitation = "&i.";
%end;
quit;
%mend;
%Loop();
%put _USER_;
Partial log:
GLOBAL SOL_1 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_2 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_3 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_4 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_5 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_6 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_7 1,2,3,4,5,6,7,8,9,10
GLOBAL SOL_8 1,2,3,4,5,6,7,8,9,10
If you want to avoid the macro altogether and having to declare the %global variables, here's a data step solution that will work as long as your dataset is sorted by Solicitation.
data _null_;
set adjusted_hours;
by solicitation;
format temp $50.;
retain temp ;
temp=CATX(',',temp, total_value);
if last.solicitation then do;
call symputx(CATS('SOL_', solicitation), temp);
call missing(temp);
end;
run;

loop through multiple rows and output related dataset SAS 9.4

I have a dataset, which is long data. Each subject has 52 week information.
The output I want is:
data new1 new2 new3 ... new52;
set old;
if week = 1 then output new1;
else if week = 2 then output new2;
else....;
run;.
Since there are 52 weeks,I want to write a macro. Don't know how to...
please see the code below using macro to create 52 datasets..
data old;
do week=1 to 52;
output;
end;
run;
%macro new(i);
data new&i;
set old;
if week=&i then output;
run;
%mend new;
%macro loop;
%do j=1 %to 52;
%new(&j);
%end;
%mend loop;
%loop;

SAS distinct level

data test1;
input var1$ var2$ ;
datalines;
1 a
2 a
3 a
1 b
2 b
1 c
;
run;
How can I create a macro var that contains all levels of var2?
For example:
%Let new_var = a b c;
If I understood the question correctly, I think you can try using proc sql for this.
proc sql;
select distinct var2 into :new_var from test1;
quit;

symbolic reference in MACRO IN sas

I have been recieving an error- symbolic reference not resolved when i run the macro in sas using following code:
Initially I select as set of Role Numbers using SQL into a list as:
PROC SQL NOPRINT; SELECT ROLENO INTO:R1-:R81 FROM ROLLNOS; QUIT;
Then a macro is used to select each individual marks and conoslidate them as :
options Mprint;
%MACRO Marks;
%DO I=1 %TO 1;
proc sql noprint;
create table Marks as select name, rollno, marks, grade from masterdata
where rollno= "&R&I.";
quit;
PROC APPEND DATA=Marks BASE=MarksSheet FORCE;RUN;
%END;
%MEND;
RUN;
%Marks;
I got an error when the sql statement is executed, Please help me resolve the issue. especially with referencing part- "&R&I."
You want to resolve to R1.
&R&I. resolves to macarovariable R (which is not available) and macrovariable I.
You need a second & before the R, because 2 & resolve to one.
If you use &&R&I, in the first step &&R resolves to &R and &I resolves to 1, so you got &R1. This will then resolve to the macrovariable R1 in second step.
Also %do I=1 %to 1 only has one iteration, is this meant to be?
options Mprint;
%MACRO Marks;
%DO I=1 %TO 1;
proc sql noprint;
create table Marks as select name, rollno, marks, grade from masterdata
where rollno= "&&R&I.";
quit;
PROC APPEND DATA=Marks BASE=MarksSheet FORCE;RUN;
%END;
%MEND;
%Marks;

How to store the distinct values of a variable in macro variable(s)

I have a group macro variable, I would like to make its classes in to macro vars. For example:
%macro test(group=);
proc freq data=foll;
tables &group / out=freqtbl;
run;
proc sql;
create table grp
(grpid char(4));
insert into grp
values('a')
values('b')
;
quit;
data freqtbl1;
merge grp freqtbl;
run;
data freqtbl2;
set freqtbl1;
call symput(grpid,&group);
run; * &a is the first group, &b is the second group;
%mend;
This works for 2 classes, but what if it has 3 or more than 3 classes?
Thanks a lot.
proc sql;
select distinct age into :cls1-:cls10
from sashelp.class;
quit;
%put &cls1 &cls2 &cls3 &cls4 &cls5 &cls6 &cls7;
You'll still have the issue of knowing when to stop when using this (like in the above, &cls7 is not resolved). Set the -:cls10 or whatever to a high enough value you don't run out of variables.
If you actually would prefer this to be in one variable,
select distinct age into :cls separated by ' '
would make &cls that has all of the values in it.
You could also do this in the data step - something like:
data _null_;
set mydata;
by myvar;
initialvar=65;
if first.myvar then do;
call symput(byte(initialvar),myvar);
initialvar+1;
end;
run;
This would require you to have it sorted. You could alternately run a similar set of code off of the PROC FREQ result dataset.
This macro will create a macro variable for each distinct observation in a column for a dataset.
Var=the column you want a set of macro variables for
dataset= the dataset you have the column in
%macro var_for_val(dataset=,var=);
proc sql noprint;
create table dist_var as
select distinct &var.
from &dataset.
;
quit;
proc sql noprint;
create table dist_Var2 as
select monotonic() as id, &var.
from dist_var
;
quit;
proc sql noprint;
select distinct max(id)
into :max_var
from dist_var2
;
quit;
%do i = 1 %to &max_var.;
%global var_&i.;
proc sql noprint;
select distinct &var.
into :var_&i.
from dist_var2
where id = &i.
;
quit;
%put &&var_&i.;
%end;
%mend;
%var_for_val(sashelp.class,var=age);
%put &var_1.;