Hello,
In SASHELP.CARS, I would like to make a PROC TABULATE by Origin. So, the first way is to make 3 PROC TABULATE like the following and replace "Asia" by USA and then Europe :
PROC TABULATE DATA = data out=tabulate; where Origin="Asia"; CLASS Make DriveTrain ; TABLE (Make), (DriveTrain) / nocellmerge ; run;
But, instead, I would like to automatize this in a macro loop. Could you please help me why the following code won’t work ? It’s the « where Origin=reg; » part that seems to be the problem. Thank you !
data data; set sashelp.cars;run;
data classes;
input id_reg reg_name $ ;
cards;
1 Asia
2 Europe
3 USA
run;
%macro comp;
%local i reg;
%do i=1 %to 3;
proc sql ;
select reg_name
into
:reg_name
from classes
where id_reg = &i.;
quit;
%let reg=reg_name;
PROC TABULATE DATA = data out=tabulate_&i;
where Origin=reg;
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
%end;
%mend comp;
%comp
Thanks to all the bits you gave, I think I have found the solution, without using the BY statemen. So here is the code that worked for me. I thank you all very much for your help!
data data; set sashelp.cars;run;
data classes;
input id_reg reg_name $ ;
cards;
1 Asia
2 Europe
3 USA
run;
%macro comp;
%local i ;
%do i=1 %to 3;
proc sql ;
select reg_name
into
:reg_name
from classes
where id_reg = &i.;
quit;
PROC TABULATE DATA = data(where=(Origin="®_name")) out=tabulate_&i;
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
%end;
%mend comp;
%comp
No need for a macro. Simply create a "3-dimensional" table like this
PROC TABULATE DATA = sashelp.cars out=tabulate;
CLASS Origin Make DriveTrain;
TABLE Origin, Make, DriveTrain / nocellmerge;
run;
Yes, I understand but I made a simple example. In the real database I work with, I need to make a macro 🙂 this is why I insist on making a macro.
Working with a database doesn't change the validity of the suggestion from @PeterClemmensen
Or if it does make a difference, please explain why.
Hi,
first, use an ampersand &:
PROC TABULATE DATA = data out=tabulate_&i;
where Origin=® /* <-------- an & */
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
second: try:
select quote(reg_name)
into...
since, I believe, you want to have:
where Orgin = "Asia"
rather than:
where Orgin = Asia
after the ®. resolution
third, this part:
%let reg=reg_name;
is redundant, reg_name is already a macrovariable so you can use it inside the proc tabulate (btw. you don't have the "&" here again)
should be: %let reg = ®_name; if you want it to work.
All the best
Bart
I guess I'm going to disagree with @yabwon
This code is easily handled with a BY statement, and no macro or macro variable is needed.
PROC TABULATE DATA = data out=tabulate;
by Origin;
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
@PaigeMiller no need for disagree. I didn't tell I like OPs code. I just pointed out places where the root cause of the "where issue" might be. 😉
All the best
Bart
Sorry, but I don't understand except putting "&". So, here is my code, with your suggestions. But it still does not work:
%macro comp; %local i reg; %do i=1 %to 3; proc sql ; select reg_name into :reg_name from classes where id_reg = &i.; quit; %let reg=input(reg_name,$10); PROC TABULATE DATA = data out=tabulate_&i; where Origin in (®); CLASS Make DriveTrain ; TABLE (Make), (DriveTrain) / nocellmerge ; run; %end; %mend comp; %comp
%macro comp; %local i reg; %do i=1 %to 3; proc sql ; select QUOTE(reg_name) into :reg_name from classes where id_reg = &i.; quit; PROC TABULATE DATA = data out=tabulate_&i; where Origin in (®_name.); CLASS Make DriveTrain ; TABLE (Make), (DriveTrain) / nocellmerge ; run; %end; %mend comp; %comp
Reply made to same question as cross posted to stackoverflow...
Use a `BY` statement to independently process like grouped subsets of a data set.
Use a `WHERE` statement to select the subset(s) to process.
Example:
ods html file='output.html' style=plateau;
proc sort data=sashelp.cars out=cars_sorted;
by origin;
run;
title; footnote;
options nocenter nodate nonumber;
PROC TABULATE DATA=cars_sorted;
by origin;
where Origin in ("Asia", "Europe", "USA");
where also make >= 'P'; * further subset for reduced size of output screen shot;
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
ods html close;
Alternatively, use a `TABLE` statement of form `<page dimension>,<row dimension>,<column dimension>` in lieu of `BY` group processing. Such a form does not need presorted data because the <page dimension> is constructed from `CLASS` variables.
Example:
PROC TABULATE DATA=sashelp.cars; /* original data, not sorted */
where Origin in ("Asia", "Europe", "USA");
where also make >= 'P'; * further subset for reduced size of output screen shot;
CLASS Origin Make DriveTrain ; /* Origin added to CLASS */
TABLE Origin, (Make), (DriveTrain) / nocellmerge ; /* Origin is page dimension */
run;
Output BY statement
Output PAGE dimensioned table
Thanks to all the bits you gave, I think I have found the solution, without using the BY statemen. So here is the code that worked for me. I thank you all very much for your help!
data data; set sashelp.cars;run;
data classes;
input id_reg reg_name $ ;
cards;
1 Asia
2 Europe
3 USA
run;
%macro comp;
%local i ;
%do i=1 %to 3;
proc sql ;
select reg_name
into
:reg_name
from classes
where id_reg = &i.;
quit;
PROC TABULATE DATA = data(where=(Origin="®_name")) out=tabulate_&i;
CLASS Make DriveTrain ;
TABLE (Make), (DriveTrain) / nocellmerge ;
run;
%end;
%mend comp;
%comp
@commitsudoku wrote:
Thanks to all the bits you gave, I think I have found the solution, without using the BY statemen. So here is the code that worked for me. I thank you all very much for your help!
data data; set sashelp.cars;run; data classes; input id_reg reg_name $ ; cards; 1 Asia 2 Europe 3 USA run; %macro comp; %local i ; %do i=1 %to 3; proc sql ; select reg_name into :reg_name from classes where id_reg = &i.; quit; PROC TABULATE DATA = data(where=(Origin="®_name")) out=tabulate_&i; CLASS Make DriveTrain ; TABLE (Make), (DriveTrain) / nocellmerge ; run; %end; %mend comp; %comp
I still think that @PeterClemmensen's suggestion of using a PAGE expression makes sense. If the purpose of the exercise is to create a data set the information for which page the table is from is in the output data set in the _page_ variable (which doesn't appear in the set if a page dimension is not used).
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
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.