Marco
Marco

Reputation: 9624

How does SAS retain the value from a previous row without the 'retain' statement?

I am working on this example which explains how to fit a standard Cox model with proc mcmc in SAS 9.3.

For the first row in the data (ind=1), S=exp(bZ) is computed along with other quantities. It is important to note that S is a new variable constructed from the columns of the original data set.

For the second row (1 < in < &N), S is incremented: S = S + exp(bZ).

Question: How does SAS retain the value of S from the previous row? I would have expected a retain statement or something equivalent...


Relevant part of the code:

if ind = 1 then do;        /* first observation         */
  S = exp(bZ);
  l = vstatus * bZ;
  v = vstatus;
 end;
 else if (1 < ind < &N) then do;
  if (lag1(time) ne time) then do;
     l = vstatus * bZ;
     l = l - v * log(S);  /* correct the loglike value   */
     v = vstatus;         /* reset v count value         */
     S = S + exp(bZ);
  end;
  else do;                /* still a tie                 */
     l = vstatus * bZ;
     S = S + exp(bZ);
     v = v + vstatus;     /* add # of nonsensored values */
  end;
 end;

Upvotes: 4

Views: 6438

Answers (2)

Robert Penridge
Robert Penridge

Reputation: 8523

It's the lag1() function that is retaining values but be careful!

The lag() function will remember the value from the previous time it was executed, not the previous row! Because your lag function only gets executed when the first if condition is not true, then there may be hard to debug problems arising from this.

I suggest changing to use a retain statement which are more explicit and easier to debug. If you do choose to keep using the lag1() function and you are having problems with the code I suggest you move it out of the conditional logic so your code looks like this:

prev_time = lag1(time);
if ind = 1 then do;        /* first observation         */
  S = exp(bZ);
  l = vstatus * bZ;
  v = vstatus;
 end;
 else if (1 < ind < &N) then do;
  if prev_time ne time then do;
     l = vstatus * bZ;
     l = l - v * log(S);  /* correct the loglike value   */
     v = vstatus;         /* reset v count value         */
     S = S + exp(bZ);
  end;
  else do;                /* still a tie                 */
     l = vstatus * bZ;
     S = S + exp(bZ);
     v = v + vstatus;     /* add # of nonsensored values */
  end;
 end;

BTW - there's lag(), lag1(), lag2(), lag3(), etc.... functions that also exist.

Upvotes: 2

vasja
vasja

Reputation: 4792

I'm sorry this is not the answer, just note what's said at http://support.sas.com/documentation/cdl/en/statug/63962/HTML/default/viewer.htm#statug_mcmc_sect017.htm

Most of the programming statements that can be used in the DATA step can also be used in PROC MCMC.

and

For the most part, the SAS programming statements work the same as they do in the DATA step, as documented in SAS Language Reference: Concepts. However, there are several differences...

So my impression is the syntax inside BEGINCNST and ENDCNST blocks is almost same as in datastep, but some of internal workings are different, which is probably the case regarding retaining of computed values (?). So probably this doesn't work same as in datastep PDV (program data vector).

Upvotes: 2

Related Questions