BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
SASuserlot
Barite | Level 11

I have the following scenario.  I am want to use multiple 'sex ' criteria to subset the data. Is it possible? what's the best way to achieve it to control sub setting conditions. In the below example I want flexibility where I can enter one or two observation for &sex macro variable. Thanks

 %macro filter(sex= );
  data class;
  set sashelp.class;
  if upcase(sex) in ( "&sex");
  *if upcase (sex) in ('F' 'M'); *how to achieve this using macro variable:
  run;
  %mend;
 %filter( sex= F );
 %*filter ( sex = %nrbquote('F' 'M'));*I wanna use like this or any other alternatives to call macro;
1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

Since you mentioned flexibility, an alternate design would be to allow the user to pass any subsetting expression,  not just values to allow subsetting by gender.  Sometimes I do stuff like:

 

%macro filter(where=1 );
  data class;
    set sashelp.class;
    where &where;
  run;
  proc print data=class ;
  run ;
%mend;

%filter()
%filter(where=(sex='F') )
%filter(where=(sex IN ('F','M')) )  /*this comma is not a problem because the parentheses mask it*/
%filter(where=(age<15))
%filter(where=(Name =: 'J' and age<=13))

For a utility macro that is designed to be used by a SAS programmer, I find the flexibility of allowing them to provide any valid WHERE clause is often valuable.

BASUG is hosting free webinars Next up: Don Henderson presenting on using hash functions (not hash tables!) to segment data on June 12. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.

View solution in original post

5 REPLIES 5
Astounding
PROC Star
A few possible combinations will do this, but here is perhaps the simplest.

First, get rid of the double quotes:

if upcase(sex) in ( &sex );

Then call the macro supplying the characters that should replace &sex:

%filter (sex = 'F' 'M')
Ksharp
Super User

Try FINDW() function:

 

 

%macro filter(sex= );
  data class;
  set sashelp.class;
  if  findw("&sex",strip(upcase(sex)));
  run;
  %mend;
 %filter ( sex =F  M )

 

PaigeMiller
Diamond | Level 26

@SASuserlot wrote:

I have the following scenario.  I am want to use multiple 'sex ' criteria to subset the data. Is it possible? what's the best way to achieve it to control sub setting conditions. In the below example I want flexibility where I can enter one or two observation for &sex macro variable. Thanks

 %macro filter(sex= );
  data class;
  set sashelp.class;
  if upcase(sex) in ( "&sex");
  *if upcase (sex) in ('F' 'M'); *how to achieve this using macro variable:
  run;
  %mend;
 %filter( sex= F );
 %*filter ( sex = %nrbquote('F' 'M'));*I wanna use like this or any other alternatives to call macro;

Remember that when you execute code that contains macros and macro variables, the values of the macro variables are used in place of the actual macro variable to generate code. Your macro above would, when executed, produce this code:

 

if upcase(sex) in ( "'F' 'M'");

 

this will not match the sex values in SASHELP.CLASS which are 'F' or 'M', it will match a record if the value of sex is "'F' 'M'", but there is no such record that has this value for sex. So you really need to "envision" what the code generated by the macro will be. Hence, when @Astounding tells you that you should remove the double quotes around &sex and use %filter (sex = 'F' 'M'), then this will produce the line of code

 

if upcase(sex) in ( 'F' 'M');

 

which is what you really want.

 

In addition, you could turn on macro debugging options

 

options mprint;

 

before you run your macro, and then you can see in the log that the code generated is not what you want it to be:

 

MPRINT(FILTER):    data class;
MPRINT(FILTER):   set sashelp.class;
MPRINT(FILTER):   if upcase(sex) in ( "'F' 'M'");
MPRINT(FILTER):   run;
--
Paige Miller
Quentin
Super User

Since you mentioned flexibility, an alternate design would be to allow the user to pass any subsetting expression,  not just values to allow subsetting by gender.  Sometimes I do stuff like:

 

%macro filter(where=1 );
  data class;
    set sashelp.class;
    where &where;
  run;
  proc print data=class ;
  run ;
%mend;

%filter()
%filter(where=(sex='F') )
%filter(where=(sex IN ('F','M')) )  /*this comma is not a problem because the parentheses mask it*/
%filter(where=(age<15))
%filter(where=(Name =: 'J' and age<=13))

For a utility macro that is designed to be used by a SAS programmer, I find the flexibility of allowing them to provide any valid WHERE clause is often valuable.

BASUG is hosting free webinars Next up: Don Henderson presenting on using hash functions (not hash tables!) to segment data on June 12. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
SASuserlot
Barite | Level 11

Thank you @Quentin     providing me the flexible options.

Thank you every one who provided the different ways to achieve the solutions. I really appreciate taking your time to  answer this and providing insights how to use the code more  useful way. 

Thank you @PaigeMiller @Astounding  @Ksharp  @Quentin .

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 486 views
  • 5 likes
  • 5 in conversation