|
a |
|
b/R/survplot.R |
|
|
1 |
# survplot.R |
|
|
2 |
# |
|
|
3 |
# 2009-02-20 |
|
|
4 |
# Aron Charles Eklund |
|
|
5 |
# http://www.cbs.dtu.dk |
|
|
6 |
# |
|
|
7 |
# depends on "survival" package. |
|
|
8 |
# |
|
|
9 |
|
|
|
10 |
# FUNCTIONS IN THIS FILE ARE THE PART OF survplot PACKAGE (version 0.0.7) |
|
|
11 |
# CREATED BY Aron Charles Eklund |
|
|
12 |
|
|
|
13 |
nrisk <- function(x, times = pretty(x$time)) { |
|
|
14 |
stopifnot(class(x) == 'survfit') |
|
|
15 |
if('strata' %in% names(x)) { |
|
|
16 |
ns <- length(x$strata) |
|
|
17 |
idx <- rep.int(1:ns, x$strata) |
|
|
18 |
str.n.risk <- split(x$n.risk, idx) |
|
|
19 |
str.times <- split(x$time, idx) |
|
|
20 |
m <- sapply(times, function(y) { |
|
|
21 |
sapply(1:ns, function(i) { |
|
|
22 |
w <- which(str.times[[i]] >= y)[1] |
|
|
23 |
ifelse(is.na(w), 0, str.n.risk[[i]][w]) |
|
|
24 |
}) |
|
|
25 |
}) |
|
|
26 |
rownames(m) <- names(x$strata) |
|
|
27 |
} else { # no strata |
|
|
28 |
m1 <- sapply(times, function(y) { |
|
|
29 |
w <- which(x$time >= y)[1] |
|
|
30 |
ifelse(is.na(w), 0, x$n.risk[w]) |
|
|
31 |
}) |
|
|
32 |
m <- matrix(m1, nrow = 1) |
|
|
33 |
} |
|
|
34 |
colnames(m) <- times |
|
|
35 |
m |
|
|
36 |
} |
|
|
37 |
|
|
|
38 |
|
|
|
39 |
addNrisk <- function(x, at = axTicks(1), |
|
|
40 |
line = 4, hadj = 0.5, |
|
|
41 |
title = 'Number at risk', title.adj = 0, |
|
|
42 |
labels, hoff = 5, col = 1) { |
|
|
43 |
m <- nrisk(x, times = at) |
|
|
44 |
ns <- nrow(m) # number of strata |
|
|
45 |
if(missing(labels)) { |
|
|
46 |
if(ns > 1) { |
|
|
47 |
labels <- names(x$strata) |
|
|
48 |
} else { |
|
|
49 |
labels <- NA |
|
|
50 |
} |
|
|
51 |
} |
|
|
52 |
label.pad <- paste(rep(' ', hoff), collapse = '') |
|
|
53 |
labels2 <- paste(labels, label.pad, sep = '') |
|
|
54 |
labels2[is.na(labels)] <- NA |
|
|
55 |
col <- rep(col, length.out = ns) |
|
|
56 |
hasTitle <- (!is.null(title)) && (!is.na(title)) |
|
|
57 |
if(hasTitle) { |
|
|
58 |
title(xlab = title, line = line, adj = title.adj) |
|
|
59 |
} |
|
|
60 |
for (i in 1:ns) { |
|
|
61 |
axis(1, at = at, labels = m[i,], |
|
|
62 |
line = line + i + hasTitle - 2, tick = FALSE, |
|
|
63 |
col.axis = col[i], hadj = hadj) |
|
|
64 |
axis(1, at = par('usr')[1], labels = labels2[i], |
|
|
65 |
line = line + i + hasTitle - 2, tick = FALSE, |
|
|
66 |
col.axis = col[i], hadj = 1) |
|
|
67 |
} |
|
|
68 |
invisible(m) |
|
|
69 |
} |
|
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
|
73 |
survplot <- function(x, data = NULL, subset = NULL, |
|
|
74 |
snames, stitle, |
|
|
75 |
col, lty, lwd, |
|
|
76 |
show.nrisk = TRUE, color.nrisk = TRUE, |
|
|
77 |
hr.pos = 'topright', legend.pos = 'bottomleft', ...) { |
|
|
78 |
eval(bquote(s <- survfit(x, data = data, subset = .(substitute(subset))))) |
|
|
79 |
if('strata' %in% names(s)) { |
|
|
80 |
if(missing(stitle)) stitle <- strsplit(deparse(x), " ~ ")[[1]][2] |
|
|
81 |
if(missing(snames)) { |
|
|
82 |
snames <- names(s$strata) |
|
|
83 |
prefx <- paste(strsplit(deparse(x), " ~ ")[[1]][2], '=', sep = '') |
|
|
84 |
if(all(substr(snames, 1, nchar(prefx)) == prefx)) { |
|
|
85 |
snames <- substr(snames, nchar(prefx) + 1, 100) |
|
|
86 |
} |
|
|
87 |
} |
|
|
88 |
ns <- length(s$strata) |
|
|
89 |
stopifnot(length(snames) == ns) |
|
|
90 |
} else { # no strata |
|
|
91 |
ns <- 1 |
|
|
92 |
snames <- NA |
|
|
93 |
legend.pos <- NA |
|
|
94 |
} |
|
|
95 |
if(show.nrisk) { |
|
|
96 |
mar <- par('mar') |
|
|
97 |
mar[1] <- mar[1] + ns + 0.5 |
|
|
98 |
opar <- par(mar = mar) |
|
|
99 |
on.exit(par(opar)) |
|
|
100 |
} |
|
|
101 |
if(missing(col)) col <- 1:ns |
|
|
102 |
if(missing(lty)) lty <- 1 |
|
|
103 |
if(missing(lwd)) lwd <- par('lwd') |
|
|
104 |
plot(s, col = col, lty = lty, lwd = lwd, ...) |
|
|
105 |
if(length(legend.pos) > 1 || !is.na(legend.pos)) { |
|
|
106 |
legend(legend.pos, legend = snames, title = stitle, |
|
|
107 |
col = col, lty = lty, lwd = lwd, bty = 'n') |
|
|
108 |
} |
|
|
109 |
if(ns == 2) { |
|
|
110 |
eval(bquote(cox <- summary(coxph(x, data = data, subset = .(substitute(subset)))))) |
|
|
111 |
hr <- format(cox$conf.int[1, c(1, 3, 4)], digits = 2) |
|
|
112 |
p <- format(cox$sctest[3], digits = 2) |
|
|
113 |
txt1 <- paste('HR = ', hr[1], ' (', hr[2], ' - ', hr[3], ')', sep = '') |
|
|
114 |
txt2 <- paste('logrank P =', p) |
|
|
115 |
legend(hr.pos, legend = c(txt1, txt2), bty = 'n') |
|
|
116 |
} |
|
|
117 |
if(show.nrisk) { |
|
|
118 |
addNrisk(s, labels = snames, |
|
|
119 |
col = if(color.nrisk) col else 1) |
|
|
120 |
} |
|
|
121 |
if(ns == 2) return(invisible(c(txt1, txt2))) |
|
|
122 |
} |