%macro pseudosurv(indata,time,dead,howmany,datatau,outdata); /* MACRO COMPUTES PSEUDOVALUES BASED ON THE KAPLAN-MEIER ESTIMATOR AT EACH TIME INPUTS: INDATA---INPUT DATA SET TIME--TIME VARIABLE DEAD---EVENT INDICATOR (1-EVENT, 0-CENSORED) HOWMANY---SAMPLE SIZE DATATAU---SUBSET OF INPUT DATA SET AT WHICH PSEUDO VALUES ARE COMPUTED DATA SET HAS SINGLE VARIABLE TIME OUTDATA---OUTPUT DATA SET WHICH CONTAINS PSUK,K=1,...,HOWMANY THE PSEUDO VALUES AT EACH TIME POINT (Note output data set includes orginal data sorted by time */ proc sort data=&indata; by &time; data keep; set &datatau; find=1; proc sort data=keep; by time; data point; set &indata; time=&time; keep=1; data point; merge point keep; by time; keep time find keep; data useme; set point; retain temp -1; if keep = 1 then temp=time; tuse=temp; if find ne 1 then delete; &time=tuse; run; /* WORKING DATA SET THAT INCLUDE A SET OF N INDICATORS WHERE FOR THE KTH INDICATOR THE EVENT IS MISSING */ data newdat; set &indata; id+1; array iobs(&howmany) dead1-dead&howmany; do j=1 to &howmany; iobs(j)=&dead; if j=id then iobs(j)=.; end; data out; set newdat; /* COMPUTE KME FOR FULL SAMPLE */ proc lifetest data=newdat noprint; time &TIME*&dead(0); survival out=sall; data sall; set sall; sall=survival; keep &time sall; %do ip=1 %to &howmany; /* COMPUTE KME FOR REDUCED SAMPLE */ proc lifetest data=newdat noprint; time &time*dead&ip(0); survival out=stmp; data stmp; set stmp; s&ip=survival; keep &time s&ip; /*merge KMEs AND COMPUTE PSEUDOVALUES FOR OBSERVATION IP*/ data pstmp; merge sall stmp; by &time; retain stemp 1; if s&ip=. then s&ip=stemp; stemp=s&ip; psu&ip=&howmany*sall- (&howmany-1)*s&ip; data out; merge out pstmp useme ; by &time; if find ne 1 then delete; keep &time psu1-psu&ip; %end; data out; set out; retain dup -1; if &time=dup then delete; else dup=&time; jd+1; data io; set out; array ps psu1-psu&howmany; do id=1 to &howmany; pseudo=ps(id); time=&time; output; end; keep time id pseudo jd; proc sort data=io ; by id; data a; set &indata; id+1; data io; merge a io; by id; proc sort data=io; by jd; proc sort data=&datatau; by time; data taus; set &datatau ; jd+1; tpseudo=time; keep jd tpseudo; data &outdata; merge io taus; by jd; drop jd id &time &dead; %mend; /******************************************************************************/ %macro pseudomean(indata,time,dead,howmany,tmax,outdata); /* MACRO ARGUMENTS INDATA--NAME OF INPUT DATA SET TIME--NAME OF TIME VARIABLE DEAD--NAME OF EVENT INDICATOR VARIABLE--(1-DEAD,0-CENSORED) HOWMANY--SAMPLE SIZE TMAX--UPPER LIMIT OF INTEGRATION FOR RESTRICTED MEAN OUTDATA--NAME OF OUTPUT DATA SET WITH PSEUDOVALUES FPR RESTRICTED MEAN IN VARIABLE "PSUMEAN" */ /* CREATE A DATA SET WHERE EVERYTHING ABOVE TMAX IS CENSORED */ DATA work; SET &indata; restime = MIN(&tmax, &time); resdead = &dead; IF restime EQ &tmax THEN resdead = 0; /* CREATE DATA SET WITH SET OF INDICATORS DEADK THAT HAS MISSING VALUE FOR KTH OBSERVATION, K=1,...,HOWMANY*/ DATA work; SET work; id+1; ARRAY iobs(&howmany) dead1-dead&howmany; DO j = 1 TO &howmany; iobs(j) = resdead; IF j = id THEN iobs(j) = .; END; /* COMPUTE RESTRICTED MEAN FOR COMPLETE SAMPLE USING PROC LIFETEST */ PROC LIFETEST DATA = work OUTSURV = km; TIME restime*resdead(0); ODS SELECT MEANS; ODS OUTPUT MEANS = mall; RUN; DATA km; SET km; IF _CENSOR_ EQ 0; PROC SORT DATA=km; BY restime; RUN; DATA km; SET km END=LAST; IF NOT(LAST) THEN DELETE; area = (&tmax - restime)*survival; KEEP area; DATA psu; MERGE km mall; meanall = mean + area; KEEP meanall; %DO ip = 1 %TO &howmany; /* COMPUTE RESTRICTED MEAN FOR SAMPLE WITH IPTH OBSERVATION DELETED USING PROC LIFETEST */ PROC LIFETEST DATA = work OUTSURV = km1; TIME restime*dead&ip(0); ODS SELECT means; ODS OUTPUT MEANS = m1; RUN; DATA km1; SET km1; IF _CENSOR_ EQ 0; PROC SORT DATA = km1; BY restime; RUN; DATA km1; SET km1 END=LAST; IF NOT(LAST) THEN DELETE; area = (&tmax - restime)*survival; KEEP area; DATA km1; MERGE km1 m1; mean = mean + area; KEEP mean; /* COMPUTE PSEUDOVALUE FOR IPTH OBSERVATION*/ DATA psu; MERGE psu km1; psu&ip=&howmany*meanall-(&howmany-1)*mean; %END; /* TRANSPOSE DATASET AND MERGE WITH RAW DATA*/ DATA out; SET psu; ARRAY y(&howmany) psu1-psu&howmany; DO j = 1 TO &howmany; psumean=y(j); OUTPUT; END; KEEP psumean; DATA &outdata; MERGE &indata out; ODS LISTING; %MEND; /******************************************************************************/ /************************************************************************/ %macro pseudoci(datain,x,r,d,howmany,datatau,dataout); /* MACRO COMPUTES PSEUDOVALUES BASED ON THE CUMUALTIVE INCIDENCE FUNCTION FOR BOTH OF TWO COMPETING RISKS TIME INPUTS: DATAIN---INPUT DATA SET X--TIME VARIABLE R--INDICCATOR OF FIRST COMPETING RISK (1-YES, 0-NO) D--INDICATOR OF SECOND COMPETING RISK HOWMANY---SAMPLE SIZE DATATAU---SUBSET OF INPUT DATA SET AT WHICH PSEUDO VALUES ARE COMPUTED DATA SET HAS SINGLE VARIABLE "TIME" DATAOUT---OUTPUT DATA SET WHICH CONATINS PSUK,K=1,...,HOWMANY THE PSEUDO VALUES AT EACH TIME POINT (Note output data set includes orginal data sorted by time) */ proc sort data=&datain; by &x; data keep; set &datatau; find=1; proc sort data=keep; by time; data point; set &datain; time=&x; keep=1; data point; merge point keep; by time; keep time find keep; data useme; set point; retain temp -1; if keep = 1 then temp=time; tuse=temp; if find ne 1 then delete; &x=tuse; proc print; /* PREPARE DATA SET WITH MISSING VALUES FOR DEADK AND RELAPSEK TO BE USED IN COMPUTING ESTIMATED CUMULATIVE INCIDENCE WITH KTH OBSERVATION DELETED*/ proc sort data=&datain; by &x; data newdat; set &datain ; id+1; array iobsd(&howmany) dead1-dead&howmany; array iobsr(&howmany) relapse1-relapse&howmany; do j=1 to &howmany; iobsd(j)=&d; iobsr(j)=&r; if j=id then do; iobsr(j)=.; iobsd(j)=.; end; end; data out; set newdat; drop dead1-dead&howmany relapse1-relapse&howmany; /* COMPUTE CI FOR 1ST (CIRALL) AND 2ND (CIDALL) FOR FULL SAMPLE, STORE IN SALL*/ %cuminc(newdat,&x,&r,&d,sall,cirall,cidall); %do ip=1 %to &howmany; /* COMPUTE CI FOR 1ST (CIRALL) AND 2ND (CIDALL) FOR REDUCED SAMPLE, STORE IN SIP*/ %cuminc(newdat,&x,relapse&ip,dead&ip,stemp,cir1,cid1); /* COMPUTE PSEUDOVALUES FOR BOTH RISK AT EVERY DATA POINT AND ADD TO FILE */ data ps; merge sall stemp; by &x; retain cirtemp 0; retain cidtemp 0; if cir1=. then cir1=cirtemp; cirtemp=cir1; rpsu&ip=&howmany*cirall- (&howmany-1)*cir1; if cid1=. then cid1=cidtemp; cidtemp=cid1; dpsu&ip=&howmany*cidall- (&howmany-1)*cid1; data out; merge out ps useme; by &x; if find ne 1 then delete; keep time rpsu1-rpsu&ip dpsu1-dpsu&ip &x; run; %end; data &dataout; set newdat; drop dead1-dead&howmany relapse1-relapse&howmany; data all; set out; array yr(&howmany) rpsu1-rpsu&howmany; array yd(&howmany) dpsu1-dpsu&howmany; do j=1 to &howmany; rpseudo=yr(j); dpseudo=yd(j); id=j; output; end; keep id time rpseudo dpseudo; proc sort data=all; by id; data &dataout; merge &dataout all; by id; retain otime -1; retain oid -1; if id eq oid and otime=time then delete; else do; oid=id; otime=time; end; %mend; /******************************************************************************/ /******************************************************************************/ %macro cuminc(datain,x,re,de,dataout,cir,cid); /* THIS MACRO COMPUTES THE CUMULATIVE INCIDENCE FUNCTIONS FOR BOTH COMPETING RISKS USING PROC PHREG OUTPUT INPUTS TO MACRO DATAIN--NAME OF INPUT DATA SET CONTAINING X--TIME TO EVENT RE--INDICCATOR OF FIRST COMPETING RISK (1-YES, 0-NO) DE--INDICATOR OF SECOND COMPETING RISK DATAOUT--NAME OF OUTPUT DATA SET CONTAINING CIR--CUMULATIVE INCIDENCE FUNCTION FOR 1ST COMPETING RISK CID--CUMULATIVE INCIDENCE FUNCTION FOR 2ST COMPETING RISK */ data work; set &datain; t=&x; r=&re; d=&de; zero=0; /* COMPUTE CRUDE CUMUALTIVE HAZARD FOR FIRST COMPETING RISK */ proc phreg data=work noprint; model t*r(0)=zero; output out=rel logsurv=chr /method=emp; /* COMPUTE CRUDE CUMUALTIVE HAZARD FOR SECOND COMPETING RISK */ proc phreg data=work noprint; model t*d(0)=zero; output out=dead logsurv=chd /method=emp; /* COMPUTE cumualtive incidence */ data both; merge rel dead; by t; retain s 1 retain cr 0; retain cd 0; retain cumincr 0; retain cumincd 0; hr=-(cr+chr); hd=-(cd+chd); /* NOTE HR AND HD ARE THE JUMPS IN THE CUMUALTIVE CRUDE HAZARDS AT THIS TIME */ cr=-chr; cd=-chd; cir=cumincr+hr*s; cumincr=cir; cid=cumincd+hd*s; cumincd=cid; s=s*(1-hr-hd); /* NOTE S IS KAPLAN-MEIER ESTIMATE IGNORING CAUSE OF FAILURE */ data &dataout; set both; &x=t; &cir=cir; &cid=cid; keep &x &cir &cid; %mend;