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

Hi,

 

I'm trying to use a macro inside a PROC NLP but when running I get the following error:

 

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric 
       operand is required. The condition was: abs(&z.)<1 
ERROR: The macro H2F1 will stop executing.

Here is my code:

 

options mlogic mprint symbolgen;

data pnbd_sample;
	infile datalines dlm='09'x  dsd truncover;
	input	@1 custID $2. 
			@4 FirstTransDt DDMMYY10. 
			@15 LastTransDt DDMMYY10. 
			@26 T 2. 
			@29 tx 2. 
			@31 x 3.;
	format 	 custID $2.
		 	 FirstTransDt DATE9. 
			 LastTransDt DATE9. 
			 T 2. 
			 tx 2. 
			 x 3.;
	datalines;
01 31/03/2014 30/06/2017 39 0 11
02 30/11/2014 30/04/2016 31 14 0
03 31/03/2014 30/09/2015 39 21 0
04 31/01/2014 30/04/2017 41 2 222
05 31/01/2014 31/05/2016 41 13 0
06 31/01/2014 31/10/2015 41 20 0
07 31/01/2014 30/06/2017 41 0 6
08 31/07/2014 31/05/2016 35 13 0
09 28/02/2014 31/05/2017 40 1 7
10 31/12/2013 30/06/2017 42 0 117
11 31/03/2014 30/06/2017 39 0 6
12 31/05/2014 31/03/2016 37 15 0
13 30/04/2014 30/06/2017 38 0 2
14 30/04/2014 30/06/2017 38 0 48
15 30/09/2014 31/12/2015 33 18 0
16 31/08/2015 30/06/2017 22 0 1
17 31/01/2014 31/12/2016 41 6 1
18 28/02/2014 30/06/2017 40 0 48
19 31/03/2014 31/12/2015 39 18 0
20 31/07/2014 30/06/2017 35 0 60
;
run;

%macro h2f1(GH,a=,b=,c=,z=); 
	gausshyper=1; tempgauss=1;
	%if abs(&z.)<1 %then %do;
		%do j=1 %to 160;
		tempgauss=tempgauss*(&a. + &j – 1)*(&b. + &j –1)* &z. /((&c. + &j –1)*&j);
		gausshyper=gausshyper + tempgauss;
		%end;
	%end;

	%if abs(&z.)=1 and &c. – &a. – &b. > 0 %then %do;
		%do j=1 %to 160;
		tempgauss=tempgauss*(&a. + &j – 1)*(&b. + &j –1)* &z. /((&c. + &j –1)*&j);
		gausshyper=gausshyper + tempgauss;
		%end;
	%end;
	
	&GH=gausshyper;

%mend h2f1;


proc nlp data=pnbd_sample tech=tr cov=2 vardef=n pcov phes;
	max lglike;
	parms r=0.1, alpha=0.1,  s=0.1,  beta=0.1;
	bounds r alpha s beta >= 0.000001;

	maxab=max(alpha, beta);
	absab=abs(alpha-beta);
	param2=s+1;
	if alpha < beta then param2=r+x;

	part1 = ((alpha**r)*(beta**s)/gamma(r)) * gamma(r+x);
	part2 = 1/((alpha+T)**(r+x)*(beta+T)**s);

	if absab=0 then do;
		F1=1 / ((maxab+tx)**(r+s+x));
		F2=1 / ((maxab+T)**(r+s+x));
	end;

	else if absab~=0 then do;
		%h2f1(F, a=r+s+x, b=param2, c=r+s+x+1, z=absab/(maxab+tx));
		F1=F/((maxab+tx)**(r+s+x));

		%h2f1(F, a=r+s+x, b=param2, c=r+s+x+1, z=absab/(maxab+T));
		F2=F/((maxab+T)**(r+s+x));
	end;

	lglike = log(part1 * (part2 + (s/(r+s+x))*(F1-F2)));

	ods output  ParameterEstimates=EstParetoNBD;
run;

 

The lines in the log just before the error are:

MLOGIC(H2F1):  Beginning execution.
MLOGIC(H2F1):  Parameter GH has value F
MLOGIC(H2F1):  Parameter A has value r+s+x
MLOGIC(H2F1):  Parameter B has value param2
MLOGIC(H2F1):  Parameter C has value r+s+x+1
MLOGIC(H2F1):  Parameter Z has value absab/(maxab+tx)
MPRINT(H2F1):   gausshyper=1;
MPRINT(H2F1):   tempgauss=1;
SYMBOLGEN:  Macro variable Z resolves to absab/(maxab+tx)

It looks as if parameters are resolving to the string expressions, rather than the numerical values, and these are being fed into the macro causing the error.

 

 

Does anyone know please how I can resolve this error?

1 ACCEPTED SOLUTION

Accepted Solutions
edmb
Obsidian | Level 7

No worries, thank you both for your assistance.

View solution in original post

6 REPLIES 6
gamotte
Rhodochrosite | Level 12

edmb wrote:

It looks as if parameters are resolving to the string expressions, rather than the numerical values, and these are being fed into the macro causing the error.

 


This is what macro language does : text substitution in order to generate source code.

When you call your macro function as follows :

%h2f1(F, a=r+s+x, b=param2, c=r+s+x+1, z=absab/(maxab+tx));

you say that, whenever &a is  encountered in the macro function source code, it should be replaced by the *text* r+s+x.

 

&z. will thus be resolved as "absab/(maxab+tx)" (wo the quotes) and your test :

 

%if abs(&z.)=1

has no sense because you are doing a character by character comparison between abs(absab/(maxab+tx)) and 1.

 

This should not be a macro language %if but a standard if test

if abs(&z.)=1 then do; ... end;

edmb
Obsidian | Level 7

Hi gamotte, thank you for your reply. I have changed my macro by removing the %s on the if statement (and kept it on the do loop) to get:

 

%macro h2f1(GH,a=,b=,c=,z=); 
	gausshyper=1; tempgauss=1;
	if abs(&z.)<1 then do;
		%do j=1 %to 160;
		tempgauss=tempgauss*(&a. + &j – 1)*(&b. + &j –1)* &z. /((&c. + &j –1)*&j);
		gausshyper=gausshyper + tempgauss;
		%end;
	end;

	if abs(&z.)=1 and &c. – &a. – &b. > 0 then do;
		%do j=1 %to 160;
		tempgauss=tempgauss*(&a. + &j – 1)*(&b. + &j –1)* &z. /((&c. + &j –1)*&j);
		gausshyper=gausshyper + tempgauss;
		%end;
	end;
	
	&GH=gausshyper;

%mend h2f1;

 

 

It now runs the do=j to 160 loop, however it now produces this error with the preceding lines:

 

MLOGIC(H2F1):  Beginning execution.
MLOGIC(H2F1):  Parameter GH has value F
MLOGIC(H2F1):  Parameter A has value r+s+x
MLOGIC(H2F1):  Parameter B has value param2
MLOGIC(H2F1):  Parameter C has value r+s+x+1
MLOGIC(H2F1):  Parameter Z has value absab/(maxab+tx)
MPRINT(H2F1):   gausshyper=1;
MPRINT(H2F1):   tempgauss=1;
SYMBOLGEN:  Macro variable Z resolves to absab/(maxab+tx)
MPRINT(H2F1):   if abs(absab/(maxab+tx))<1 then do;
MLOGIC(H2F1):  %DO loop beginning; index variable J; start value is 1; stop value is 160; by 
      value is 1.  
SYMBOLGEN:  Macro variable A resolves to r+s+x
SYMBOLGEN:  Macro variable J resolves to 1
NOTE 137-205: Line generated by the invoked macro "H2F1".
124           tempgauss=tempgauss*(&a. + &j – 1)*(&b. + &j –1)* &z. /((&c. + &j –1)*&j);
                                            _
                                            22
124      ! gausshyper=gausshyper + tempgauss;
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, ), *, **, +, -, /, <, <=, 
              <>, =, >, ><, >=, AND, EQ, GE, GT, IN, LE, LT, NE, NOTIN, OR, ^<, ^=, ^>, |, ||, 
              ~<, ~=, ~>.  

 

 

Thank you, the initial problem has resolved but now I'm unsure how to resolve this new one (apologies, I'm still learning the macro side of SAS).

Astounding
PROC Star

You're doing well at identifying the problems.  This one is entirely different.  Your dash is not really a dash, it's really a wider dash.

 

Replace all the dashes.  Just remove the character, and replace it by typing the proper dash on your keyboard.  This sometimes happens when cutting and pasting code using various editors.

edmb
Obsidian | Level 7

@Astounding wrote:

 

Replace all the dashes.  Just remove the character, and replace it by typing the proper dash on your keyboard.  This sometimes happens when cutting and pasting code using various editors.


What trickery is this?! Cheers!

 

Though now I get this... feels like we're getting closer!

 

MLOGIC(H2F1):  %DO loop index variable J is now 161; loop will not iterate again.
MPRINT(H2F1):   end;
SYMBOLGEN:  Macro variable GH resolves to F
MPRINT(H2F1):   F=gausshyper;
MLOGIC(H2F1):  Ending execution.
128        		F2=F/((maxab+T)**(r+s+x));
129        	end;
130        
131        	lglike = log(part1 * (part2 + (s/(r+s+x))*(F1-F2)));
132        
133        	ods output  ParameterEstimates=EstParetoNBD;
134        run;

NOTE: Your code contains 1319 program statements.
NOTE: Gradient is computed using analytic formulas.
NOTE: Hessian is computed using analytic formulas.
ERROR: Execution Errors for _OBS_= 4 :
ERROR: There are references to missing variables when the program code is executed for _OBS_= 4
WARNING: Your program statements cannot be executed completely.
WARNING: In a total of 1 calls an error occurred during execution of the program statements. NLP 
         attempted to recover by using a shorter step size.
NOTE: The data set WORK.ESTPARETONBD has 4 observations and 5 variables.
NOTE: There were 20 observations read from the data set WORK.PNBD_SAMPLE.
NOTE: The PROCEDURE NLP printed pages 1-2.
NOTE: PROCEDURE NLP used (Total process time):
      real time           2.01 seconds
      cpu time            1.98 seconds

EDIT: I have located why this error occurs... the formulae:

 

part1 = ((alpha**r)*(beta**s)/gamma(r)) * gamma(r+x);
part2 = 1/((alpha+T)**(r+x)*(beta+T)**s);

breakdown at very large x values... I can understand why they might... though why should they? Does SAS not have a memory/calculation limit?

Astounding
PROC Star

At least you're past the syntax errors.

 

I don't think I can help with this procedure in particular.  But at least the log telling you the observation that is causing trouble.  Perhaps you could investigate the data values on that observation.  Any missing values in the data?

edmb
Obsidian | Level 7

No worries, thank you both for your assistance.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 6 replies
  • 1440 views
  • 2 likes
  • 3 in conversation