Section 5.2
Estimating the Survival Function for Left, Double, and Interval Censoring
Example 5.1 illustrating Turnbull’s algorithm. We therefore create Table 5.1, Table 5.2 and Table 5.3 all through data steps and proc sql to show the steps.
data table5_1;
input age num_lcen num_event num_rcen;
cards;
0 0 0 0
10 0 4 0
11 0 12 0
12 0 19 2
13 1 24 15
14 2 20 24
15 3 13 18
16 2 3 14
17 3 1 6
18 1 0 0
19 0 4 0
;
run;
proc sql noprint;
select sum(num_event)+ sum(num_rcen) into :total
from table5_1;
quit;
data table5_1a;
set table5_1;
id = _n_;
elag = lag(num_event);
rlag = lag(num_rcen);
retain y &total survival 1;
if _n_ >= 2 then y = y - rlag - elag;
survival = survival*(1-num_event/y);
drop elag rlag;
run;
proc print data=table5_1a noobs;
var id num_lcen num_event num_rcen y survival;
run;
num_
id num_lcen event num_rcen y survival
1 0 0 0 179 1.00000
2 0 4 0 179 0.97765
3 0 12 0 175 0.91061
4 0 19 2 163 0.80447
5 1 24 15 142 0.66850
6 2 20 24 103 0.53870
7 3 13 18 59 0.42000
8 2 3 14 28 0.37500
9 3 1 6 11 0.34091
10 1 0 0 4 0.34091
11 0 4 0 4 0.0000
Table 5.2, step 1 of Turnbull’s algorithm.
data table5_2;
set table5_1a;
keep survival;
run;
proc sort data = table5_2;
by descending survival ;
run;
proc transpose data=table5_2 out=long52 (drop = _name_);
var survival;
run;
proc sql;
create table table5_2b as
select *
from table5_1a , long52;
quit;
data table5_2c;
set table5_2b nobs=last;
slag = lag(survival);
array s(11) col1-col11;
array p(11);
do i = 2 to 10;
p(i) = (slag - survival)/(1 - s(i+1));
end;
if _n_ = last then
do i = 2 to 10;
p(i) = 0;
end;
run;
proc print data = table5_2c ;
var p4-p9;
where p2 ne . ;
run;
Obs p4 p5 p6 p7 p8 p9 2 0.06741 0.04844 0.03853 0.03575 0.03390 0.03390 3 0.20223 0.14533 0.11558 0.10726 0.10171 0.10171 4 0.32020 0.23010 0.18301 0.16983 0.16105 0.16105 5 0.41016 0.29474 0.23443 0.21755 0.20629 0.20629 6 0.39158 0.28139 0.22380 0.20769 0.19695 0.19695 7 0.35806 0.25731 0.20465 0.18991 0.18009 0.18009 8 0.13575 0.09755 0.07759 0.07200 0.06828 0.06828 9 0.10284 0.07390 0.05878 0.05455 0.05172 0.05172 10 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 11 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
Table 5.3, the first step of the Self-Consistency Algorithm.
data table5_3;
set table5_2c;
array p(6) p4-p9;
if _n_ >=6 then
do i = 1 to _n_ - 5;
p(i) = 0;
end;
if _n_ = 1 then dhat = 0;
else dhat = num_event + p4 + 2*p5 + 3*p6 + 2*p7 + 3*p8 + p9;
run;
proc sql noprint;
select sum(dhat) + sum(num_rcen) into :totaly
from table5_3;
quit;
data table5_3a;
set table5_3;
dlag = lag(dhat);
rlag = lag(num_rcen);
retain yhat &totaly survival1 1;
if _n_>=2 then yhat = yhat - dlag - rlag;
survival1 = survival1*abs((1-dhat/yhat));
run;
proc print data=table5_3a noobs;
var id age dhat num_rcen yhat survival1;
run;
id age dhat num_rcen yhat survival1
1 0 0.0000 0 191.000 1.00000
2 10 4.4870 0 191.000 0.97651
3 11 13.4610 0 186.513 0.90603
4 12 21.3133 2 173.052 0.79444
5 13 26.9632 15 149.739 0.65139
6 14 22.4374 24 107.775 0.51578
7 15 14.7141 18 61.338 0.39205
8 16 3.4171 14 28.624 0.34525
9 17 1.2069 6 11.207 0.30807
10 18 0.0000 0 4.000 0.30807
11 19 4.0000 0 4.000 0.00000
Example 5.2 on estimation procedure for interval-censored data. It uses the data described in section 1.18. SAS currently doesn’t have a standard procedure on nonparametric survival analysis for interval-censored data. But it has a macro %ice that performs the analysis. Macro %ice makes use of a utility program called xmacro.sas. Program ice.sas is located at Both of the programs can be found from SAS. Here is a link to %ice and xmacro.sas. You need to download both programs for Example 5.2.
Section 5.3
Estimation of the Survival Function for Right-Truncated Data
This section uses the data set described in section 1.19. We created a SAS data step for it.
Example 6.3, Table 6.3 and Figure 6.8. The first part of the program creates the hazard rate based on the Iowa life table. The macro does the computation for table 6.3 including the confidence intervals. We notice that the output produced below does not match with Table 6.3 completely. The data for table 6.3 is then used for Figure 6.8.
proc sort data = iowa_60_mortality;
by male;
run;
data table6_2;
set iowa_60_mortality;
by male;
ls = lag(survival);
if ~first.male then do;
hr = log(ls) - log(survival); end;
drop survival;
if hr ~=.;
run;
%macro rel_mortality(data, age, time, death, outdata);
proc sql noprint;
select count( distinct &time) into :max_num
from &data
where &death = 1;
quit;
proc sql noprint;
select count(&time) into :dpoint separated by ' '
from &data
where &death = 1
group by &time;
quit;
proc sql noprint;
select distinct &time into :tpoint separated by ' '
from &data
where &death = 1;
quit;
%do k = 1 %to &max_num;
%let p = %scan(&tpoint, &k);
proc sql noprint;
select sum(y.hr) into :q&k
from &data as x, table6_2 as y
where 1-x.female = y.male and x.age + &p + 1 = y.age and x.time >= &p ;
quit;
%end;
data &outdata;
b = 0;
v = 0;
%do i = 1 %to &max_num;
t = %scan(&tpoint, &i);
d = %scan(&dpoint, &i);
q = &&q&i;
b = b + d/q;
v = v + d/q**2;
s = sqrt(v);
lc = b/exp(1.96*s/b);/*log-transformed confidence interval*/
uc = b*exp(1.96*s/b);
output;
%end;
run;
proc print data= &outdata noobs;
var t d q b v s lc uc;
run;
%mend rel_mortality;
%rel_mortality(sec1_15, age, time, death, temp)
t d q b v s lc uc
1 2 0.05932 33.718 568.44 23.8420 8.4325 134.822
2 1 0.04964 53.861 974.20 31.2122 17.2982 167.707
11 1 0.08524 65.593 1111.84 33.3443 24.2183 177.654
14 1 0.10278 75.323 1206.51 34.7349 30.5066 185.979
22 2 0.18238 86.289 1266.64 35.5899 38.4478 193.660
24 1 0.21559 90.928 1288.15 35.8909 41.9472 197.100
25 1 0.17002 96.809 1322.75 36.3696 46.3583 202.164
26 1 0.19441 101.953 1349.20 36.7315 50.3179 206.574
28 1 0.18434 107.377 1378.63 37.1299 54.5220 211.473
32 1 0.18562 112.765 1407.66 37.5187 58.7436 216.465
35 1 0.16755 118.733 1443.28 37.9905 63.4180 222.296
40 1 0.04902 139.135 1859.50 43.1219 75.7912 255.419
symbol i = stepjl;
axis1 order = (0 to 250 by 50) label=(a=90 'Estimated Cumulative Relative Mortality, B(t)')
minor = none;
axis2 order = (0 to 40 by 10) minor = none label=('Years on Study');
proc gplot data= temp;
plot uc*t b*t lc*t/overlay vaxis = axis1 haxis = axis2;
run;
quit;

Example 6.3 continued on page 169. Table 6.4, Figure 6.9 and Figure 6.10. The proc sql step and data steps below prepares us to create Table 6.4. The macro program generates Table 6.4.
proc sql;
create table table6_4 as
select time, sum(death) as d, sum(death=0) as censor
from sec1_15
group by time;
quit;
data table6_4a;
do time = 1 to 40;
output; end;
run;
data table6_4b;
merge table6_4 table6_4a ;
by time;
if d = . then d = 0;
if censor = . then censor = 0;
retain y 26;
ld = lag(d);
lc = lag(censor);
if _n_>1 then y = y-ld - lc;
drop ld lc;
run;
%macro theta(data, time, max, outdata);
%do k = 1 %to &max;
proc sql noprint;
select sum(y.hr) into :q&k
from &data as x, table6_2 as y
where 1-x.female = y.male and x.age + &k = y.age and x.time > &k - 1 ;
quit;
%end;
data &outdata;
set table6_4b;
retain theta 0;
retain p var_a 0;
retain h 0;
retain s1 1;
q = symget('q'||left(_n_));
theta = theta + q/y;
p = p + d/y;
h = h + d/y;
s1 = s1*(1-d/y);
var_a = var_a + d/y**2;
a = p - theta;
sda = sqrt(var_a);
survival = exp(-theta);
sc = s1/survival;
drop q p censor;
run;
proc print data = temp noobs;
var time d y h theta a sda s1 survival sc;
run;
%mend;
%theta(sec1_15, time, 40, temp)
time d y h theta a sda s1 survival sc
1 2 26 0.07692 0.00213 0.07479 0.05439 0.92308 0.99787 0.92505
2 1 24 0.11859 0.00406 0.11453 0.06852 0.88462 0.99595 0.88822
3 0 23 0.11859 0.00594 0.11265 0.06852 0.88462 0.99408 0.88988
4 0 23 0.11859 0.00794 0.11065 0.06852 0.88462 0.99209 0.89167
5 0 23 0.11859 0.01008 0.10851 0.06852 0.88462 0.98997 0.89358
6 0 23 0.11859 0.01237 0.10622 0.06852 0.88462 0.98771 0.89563
7 0 23 0.11859 0.01483 0.10376 0.06852 0.88462 0.98528 0.89783
8 0 23 0.11859 0.01747 0.10112 0.06852 0.88462 0.98269 0.90020
9 0 23 0.11859 0.02032 0.09827 0.06852 0.88462 0.97989 0.90277
10 0 23 0.11859 0.02341 0.09518 0.06852 0.88462 0.97686 0.90557
11 1 23 0.16207 0.02679 0.13528 0.08115 0.84615 0.97357 0.86913
12 0 22 0.16207 0.03029 0.13178 0.08115 0.84615 0.97016 0.87218
13 0 22 0.16207 0.03414 0.12793 0.08115 0.84615 0.96643 0.87554
14 1 22 0.20752 0.03838 0.16914 0.09301 0.80769 0.96235 0.83929
15 0 21 0.20752 0.04279 0.16473 0.09301 0.80769 0.95811 0.84300
16 0 21 0.20752 0.04811 0.15941 0.09301 0.80769 0.95303 0.84750
17 0 21 0.20752 0.05297 0.15455 0.09301 0.80769 0.94841 0.85163
18 0 21 0.20752 0.05882 0.14871 0.09301 0.80769 0.94288 0.85662
19 0 21 0.20752 0.06522 0.14230 0.09301 0.80769 0.93686 0.86213
20 0 21 0.20752 0.07222 0.13530 0.09301 0.80769 0.93032 0.86818
21 0 21 0.20752 0.08035 0.12717 0.09301 0.80769 0.92280 0.87527
22 2 21 0.30276 0.08872 0.21405 0.11483 0.73077 0.91511 0.79856
23 0 19 0.30276 0.09674 0.20603 0.11483 0.73077 0.90780 0.80499
24 1 19 0.35539 0.10611 0.24928 0.12632 0.69231 0.89932 0.76981
25 1 18 0.41095 0.11683 0.29411 0.13800 0.65385 0.88973 0.73488
26 1 17 0.46977 0.12554 0.34423 0.15001 0.61538 0.88202 0.69770
27 0 16 0.46977 0.13628 0.33349 0.15001 0.61538 0.87260 0.70524
28 1 16 0.53227 0.14737 0.38490 0.16251 0.57692 0.86297 0.66853
29 0 15 0.53227 0.15924 0.37303 0.16251 0.57692 0.85279 0.67651
30 0 15 0.53227 0.17294 0.35933 0.16251 0.57692 0.84119 0.68584
31 0 13 0.53227 0.18722 0.34505 0.16251 0.57692 0.82926 0.69571
32 1 11 0.62318 0.20356 0.41962 0.18621 0.52448 0.81582 0.64288
33 0 10 0.62318 0.22147 0.40171 0.18621 0.52448 0.80134 0.65450
34 0 8 0.62318 0.24193 0.38125 0.18621 0.52448 0.78511 0.66803
35 1 7 0.76604 0.26380 0.50223 0.23470 0.44955 0.76812 0.58526
36 0 4 0.76604 0.28556 0.48048 0.23470 0.44955 0.75160 0.59813
37 0 3 0.76604 0.31402 0.45202 0.23470 0.44955 0.73051 0.61540
38 0 2 0.76604 0.35176 0.41428 0.23470 0.44955 0.70345 0.63907
39 0 2 0.76604 0.39333 0.37271 0.23470 0.44955 0.67481 0.66619
40 1 1 1.76604 0.43709 1.32895 1.02717 0.00000 0.64591 0.00000
axis1 order = (0 to 1.5 by .5) label=(' ') minor = none;
axis2 order = (0 to 40 by 10) label=('Years on Study') minor = none;
symbol1 i = stepjl c = black;
symbol2 i = join c = blue;
symbol3 i = join c = red;
proc gplot data = temp;
plot h*time = 1 theta*time = 2 a*time = 3 /overlay vaxis = axis1 haxis=axis2;
run;
quit;

axis1 order = (0 to 1 by .2) label=(' ') minor = none;
axis2 order = (0 to 40 by 10) label=('Years on Study') minor = none;
symbol1 i = stepjl c = black;
symbol2 i = join c = blue;
symbol3 i = join c = red;
proc gplot data = temp;
plot s1*time = 1 survival*time = 2 sc*time = 3 /overlay vaxis = axis1
haxis=axis2;
run;
quit;
Section 6.4 Bayesian Nonparametric Methods
Under construction.

