NicChik
NicChik

Reputation: 73

Macro is converting numeric inputs to character. How to change it back to numeric?

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

Answers (2)

Tom
Tom

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

user133631
user133631

Reputation: 228

Try nesting the %eval functions like so:

%eval(%eval(&split <= 0) or %eval(&split >= 1))

Upvotes: 0

Related Questions