先看一下SPEC中关于这两个变量生成逻辑:
这两个变量含义很容易理解,就是基线值。编程思路是在基线记录中生成BASE/BNRIND,再保留到该PARAMCD中的其他记录中。我们看一下代码:BASE(Baseline Value):AVAL where ABLFL=Y per parameter
BNRIND(Baseline Reference Range Indicator):ANRIND where ABLFL=Y per parameter
生成ABLFL后,在每一个PARAMCD中,按ABLFL降序排序。这样情况下,基线记录ABLFL=‘Y’,非基线记录ABLFL为空。因此,基线记录就排在首行了,接着把首行记录值(BASE/BNRIND)retain下来,使得非基线记录含有基线记录的变量值。
这里有一个注意点:
if ablfl = 'Y' then do; base_= aval; bnrind_=anrind; end;
if first.paramcd then do; base = base_; baseadt; bnrind=bnrind_; end;
这里为什么不直接?
if first.paramcd and ablfl = 'Y' then do; base = aval; baseadt; bnrind=anrind; end;
这里要谈到ablfl的定义了:
For each parameter, set to Y for the last record (sort by ADT in ascending order) with AVAL not null and ATPT null and NULL< ADT <=ADSL.TRTSDT
定义为基线值的记录,AVAL值必须是非空。如果某一PARAMCD中,AVAL都为空值,即ablfl也都为空值。这时候运行到“if first.paramcd and ablfl = 'Y' then do;”这一步就不执行下面的赋值语句了,这样会产生赋值错误。可能有人会说,这样不是正好吗?变量BASE保留基线记录的值,如果这个PARAMCD内AVAL都为空,没有基线,所以就不用赋值了。这种思路没问题,可是具体到SAS语句的运行时,如果不执行赋值语句的话,RETAIN语句会继续起作用,变量BASE记录的就是上一个PARAMCD的BASE值了。而在条件为“if first.paramcd then do;”情况下,在某一PARAMCD内,没有基线记录时也会进行赋值语句,只不过赋值是空值。因为不符合上一步条件ablfl = 'Y', BASE_ 已经被赋值为空值。这就保证无基线记录时,该PARAMCD内的BASE值为空,不会是前一个PARAMCD的值。
这个例子对于我们有一个很好的启示,我们再理解变量生成逻辑的同时,也要注意SAS编程运行机制,避免一些意想不到的错误。