Diff of /R/survplot.R [000000] .. [226bc8]

Switch to unified view

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
}