Reputation: 73
I created a macro to split a dataset into a training and validation set. I noticed that the following %if statement was not evaluating correctly and recently learned that it's because the macro processor does not make a distinction between character and numeric values as the rest of SAS does (link to SAS documentation). I confirmed this by using the %eval function as shown below:
%else %if %eval(&split) <= 0 or %eval(&split) >= 1 %then %do;
%put ERROR: The specified split of the data must be within the following range of real numbers (0,1].;
%end;
How can I fix this so that it will read my input for the macro variable "split" correctly as a decimal?
The following sample code can be used:
data test (drop=i);
do i=1 to 1000;
a=round(uniform(1)*4,.01);
b=round(uniform(1)*10,.01);
c=round(uniform(1)*7.5,.01);
if b<2 then d=1;
else d=0;
if i<500 then y=1;
else y=0;
output;
end;
stop;
run;
%macro train_valid(split=);
%if &split = %then %put ERROR: Missing an input. Check to make sure the macro variable has an input.;
%else %if &split <= 0 or &split >= 1 %then %do;
%put ERROR: The specified split of the data must be within the following range of real numbers (0,1].;
%end;
%else %do;
proc surveyselect data=test samprate=&split seed=1000 out=Sample outall
method=srs noprint;
run;
data test_train;
set Sample;
where selected = 1;
run;
data test_valid;
set Sample;
where selected = 0;
run;
%end;
%mend;
%train_valid(split=.75);
Upvotes: 0
Views: 1005
Reputation: 51566
I think your issue is that by default SAS will evaluate conditions in %IF, %WHILE, etc using the %EVAL()
function which can only handle integer comparisons. If you want to use floating point values or date literals then you need to explicitly use %SYSEVALF()
to test the conditions.
%if %sysevalf(&split <= 0 or &split >= 1) %then %do;
Upvotes: 1
Reputation: 228
Try nesting the %eval functions like so:
%eval(%eval(&split <= 0) or %eval(&split >= 1))
Upvotes: 0