DATA Step, Macro, Functions and more

Macro to check range of variables

Accepted Solution Solved
Reply
Frequent Contributor
Posts: 142
Accepted Solution

Macro to check range of variables

Hi!

 

I would like some help trouble shooting a macro.  I found this  macro online for range checking my variables.  I know there are a lot of ways to range check, but I am hoping to be abl eto build a spreadsheet to not values outside of my acceptable ranges.  This one seems to work with that concepts, but I cannot get the macro to work with my sample data.  I've also attached the pdf with the macro explained by the author.  Any help is greatly appreciated!!

 

data rangetbl;
input @1 errorid $2.
	@3 errorvar $12.
	@15 errorsas $40.;
datalines;
1  usmil	  not(usmil in: (0,1))
2  usciv 	  not(usciv in: (0,1))
3  nonusmil   not(nonusmil in: (0,1))
4  nonusciv   not(nonusciv in: (0,1))
5  EPW 	      not (EPW in: (0,1))
;
run;

data dataset;
input
@1 medid 3.
@4 usmil 3.
@7 usciv 3.
@10 nonusmil 3.
@13 nonusciv 3.
@16 EPW 3.;
datalines;
1	0	0	1	1	2
2	1	0	1	0	0
3	3	1	2	0	0
4	0	2	1	0	0
;
run;

proc sort data=dataset;
by medid;
run;



data _null_;
set rangetbl end=last;
retain count;
	if _n_=1 then count=0;
	count=count+1;
	call symput ('id'||left (trim(put(count,5.))),
		trim (errorid));
	call symput ('var'||left (trim(put(count,5.))),
		trim (errorvar));
	call symput ('code'||left (trim(put(count,5.))),
		trim (errorsas));
if last then call symput
	('checkct',left(trim(put(count,8.))));
run;


%macro checkvar (id, var, check);
if &check then do;
	errorid="&id.";
	errorvar="&var.";
	errorval=&var;
	output;
	end;
%mend checkvar;

data error_ds (keep=medid errorid errorvar errorval);
set dataset;
length errorid errorvar $8 errorval 8.;
%macro runcheck;
	%do j=1 %to &checkct;
	%checkvar (%str (&&id&j),
				%str (&&var&j)
				%str (&&code&j));
			%end;
	%mend runcheck;
	%runcheck;
	run;

 


Accepted Solutions
Solution
‎08-30-2017 11:18 AM
Super User
Posts: 11,343

Re: Macro to check range of variables

Have you looked at the dataset rangetble? There is a chance that the forum has reformatted you text but when I run the code as copy and pasted from the window I get a value of "usmil not" for the first errorvar. I don't have the option expandtabs set and it appears that you have some tabs in the line so that may be a minor bit.

 

You may also want to consider using some of the features that have appeared since 1999 such as Call symputx which removes leading and trailing blanks of the value so you can reduce the trim(left( code.

Also insted of || there is a nice selection of concatenation functions. and Since Count = _n_ in the data _null_ for creating the macro variables as used why add the variable? That approach might be needed if you were doing something with repeaded values but not here.

 

data _null_;
set work.rangetbl end=last;
retain count;
	if _n_=1 then count=0;
	count=count+1;
	call symputx (cats('id',_n_),errorid);
	call symputx (cats('var',_n_),errorvar);
	call symputx (cats('code',_n_),errorsas);
   if last then call symputx('checkct',_n_);
run;

If you are interested in seeing what the macro variables look like use: %put _user_; to see all of your created variables in the current scope.

 

 

Also when you do this:

data error_ds (keep=medid errorid errorvar errorval);
set dataset;
length errorid errorvar $8 errorval 8.;
%macro runcheck; /* <= %macro ends the previously started data set*/
	%do j=1 %to &checkct;
	%checkvar (%str (&&id&j),
				%str (&&var&j)    /*<=missing ,*/
				%str (&&code&j));
			%end;
	%mend runcheck;

the macro definition ends the data step as a boundary like a Run statement or a Proc.

 

Define the macro before the data step that wants to use it. AND heres likely the fatal part: you are missing a , after the VAR parameter call to %checkvar

 

Try

%macro runcheck;
	%do j=1 %to &checkct;
	%checkvar (%str (&&id&j),
				 %str (&&var&j),
				%str (&&code&j));
   %end;
%mend runcheck;

data error_ds (keep=medid errorid errorvar errorval);
   set dataset;
   length errorid errorvar $8 errorval 8.;
	%runcheck;
run;

View solution in original post


All Replies
Solution
‎08-30-2017 11:18 AM
Super User
Posts: 11,343

Re: Macro to check range of variables

Have you looked at the dataset rangetble? There is a chance that the forum has reformatted you text but when I run the code as copy and pasted from the window I get a value of "usmil not" for the first errorvar. I don't have the option expandtabs set and it appears that you have some tabs in the line so that may be a minor bit.

 

You may also want to consider using some of the features that have appeared since 1999 such as Call symputx which removes leading and trailing blanks of the value so you can reduce the trim(left( code.

Also insted of || there is a nice selection of concatenation functions. and Since Count = _n_ in the data _null_ for creating the macro variables as used why add the variable? That approach might be needed if you were doing something with repeaded values but not here.

 

data _null_;
set work.rangetbl end=last;
retain count;
	if _n_=1 then count=0;
	count=count+1;
	call symputx (cats('id',_n_),errorid);
	call symputx (cats('var',_n_),errorvar);
	call symputx (cats('code',_n_),errorsas);
   if last then call symputx('checkct',_n_);
run;

If you are interested in seeing what the macro variables look like use: %put _user_; to see all of your created variables in the current scope.

 

 

Also when you do this:

data error_ds (keep=medid errorid errorvar errorval);
set dataset;
length errorid errorvar $8 errorval 8.;
%macro runcheck; /* <= %macro ends the previously started data set*/
	%do j=1 %to &checkct;
	%checkvar (%str (&&id&j),
				%str (&&var&j)    /*<=missing ,*/
				%str (&&code&j));
			%end;
	%mend runcheck;

the macro definition ends the data step as a boundary like a Run statement or a Proc.

 

Define the macro before the data step that wants to use it. AND heres likely the fatal part: you are missing a , after the VAR parameter call to %checkvar

 

Try

%macro runcheck;
	%do j=1 %to &checkct;
	%checkvar (%str (&&id&j),
				 %str (&&var&j),
				%str (&&code&j));
   %end;
%mend runcheck;

data error_ds (keep=medid errorid errorvar errorval);
   set dataset;
   length errorid errorvar $8 errorval 8.;
	%runcheck;
run;
Frequent Contributor
Posts: 142

Re: Macro to check range of variables

@ballardw THANK YOU so much! It worked perfectly with your suggestions!
☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 2 replies
  • 133 views
  • 0 likes
  • 2 in conversation