BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
commitsudoku
Obsidian | Level 7

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

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
commitsudoku
Obsidian | Level 7

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="&reg_name")) out=tabulate_&i;
		CLASS Make DriveTrain   ; 
		TABLE (Make), (DriveTrain)   / nocellmerge ; 
		run;

	%end;
%mend comp;
%comp

View solution in original post

11 REPLIES 11
PeterClemmensen
Tourmaline | Level 20

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;
commitsudoku
Obsidian | Level 7

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. 

PaigeMiller
Diamond | Level 26

Working with a database doesn't change the validity of the suggestion from @PeterClemmensen 

 

Or if it does make a difference, please explain why.

--
Paige Miller
yabwon
Amethyst | Level 16

Hi,

 

first, use an ampersand &:

 

PROC TABULATE DATA = data out=tabulate_&i;
		where Origin=&reg; /* <-------- 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 &reg. 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 = &reg_name; if you want it to work.

 

All the best

Bart

 

 

 

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



PaigeMiller
Diamond | Level 26

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;
--
Paige Miller
yabwon
Amethyst | Level 16

@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

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



commitsudoku
Obsidian | Level 7

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 (&reg);
		CLASS Make DriveTrain   ; 
		TABLE (Make), (DriveTrain)   / nocellmerge ; 
		run;

	%end;
%mend comp;
%comp
yabwon
Amethyst | Level 16
%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 (&reg_name.);
		CLASS Make DriveTrain   ; 
		TABLE (Make), (DriveTrain)   / nocellmerge ; 
		run;

	%end;
%mend comp;
%comp
_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



RichardDeVen
Barite | Level 11

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
nAiTY

 

Output PAGE dimensioned table
NapaU

 

commitsudoku
Obsidian | Level 7

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="&reg_name")) out=tabulate_&i;
		CLASS Make DriveTrain   ; 
		TABLE (Make), (DriveTrain)   / nocellmerge ; 
		run;

	%end;
%mend comp;
%comp
ballardw
Super User

@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="&reg_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).

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 3025 views
  • 2 likes
  • 6 in conversation