[f2e496]: / R / dataResults.R

Download this file

326 lines (261 with data), 15.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# This file contains the public functions associated
# with the results of the predict from data simulations
##' @include eventData.R accrual.R longlagSettings.R simQOutput.R singleSimDetails.R eventPrediction_package.R
NULL
##' Class that contains results from the simulating event predictions
##' from Data
##' @slot limit The confidence interval width used by recQuantiles, eventQuantiles and dropoutQuantiles
##' If limit = 0.05 then the CI is the 5th - 95th percentile
##' @slot eventQuantiles The dates on which the median and CI of each event is expected to occur
##' @slot event.data The EventData object used when simulating events
##' @slot accrualGenerator The AccrualGenerator object used to recruit new subjects
##' @slot Naccrual The number of additional subjects recruited for each simulation
##' @slot time.pred.data A data frame giving the expected number of events (and CI intervals) for
##' given target dates. See vignette for further details
##' @slot event.pred.data A data frame giving the expected date (and CI intervals) for given
##' target numbers of events occurring. See vignette for further details
##' @slot recQuantiles The dates on which the median and CI of each recruitment is expected to occur
##' @slot dropoutQuantiles The dates on which the median and CI of each event is expected to occur
##' @slot singleSimDetails A SingleSimDetails object containing the subject level details of the simulation
##' see SingleSimDetails class documentaion for further details.
##' @slot dropout.shape The Weibull shape parameter of the dropout risk used for the simulations
##' @slot dropout.rate The Weibull rate parameter of the dropout risk used for the simulations (in units of day^{-1}).
##' If no dropout then this is 0
##' @slot simParams The \code{FromDataSimParam} object which contains the information
##' used to generate the survial times
##' @seealso \code{\link{show,FromDataResults-method}}, \code{\link{predict,FromDataResults-method}},
##' \code{\link{summary,FromDataResults-method}}
##' @export
setClass("FromDataResults",
slots=list(limit = "numeric",
eventQuantiles="SimQOutput",
event.data = "EventData",
accrualGenerator="AccrualGenerator",
Naccrual="numeric",
time.pred.data="data.frame",
event.pred.data="data.frame",
recQuantiles = "SimQOutput",
dropoutQuantiles="SimQOutput",
singleSimDetails="SingleSimDetails",
dropout.shape="numeric",
dropout.rate="numeric",
simParams="FromDataSimParam")
)
##' @name show
##' @rdname show-methods
##' @aliases show,FromDataResults-method
##' @export
setMethod( "show",
"FromDataResults",
function(object) {
cat("FromDataResults object, use object@param to access individual columns:\n")
cat("limit: ")
cat(object@limit)
cat("\nEvent Times\n")
show(object@eventQuantiles)
cat(".. use object@EventData@param to access individual columns:\n")
cat(str( object@event.data@subject.data))
})
##' @name predict
##' @rdname predict-methods
##' @aliases predict,FromDataResults-method
##' @export
setMethod("predict","FromDataResults",
function(object,time.pred=NULL,event.pred=NULL){
if(is.null(time.pred) && is.null(event.pred)){
stop("No predictions requested! Please enter either an event.pred or time.pred argument")
}
max.num.events <- length(object@eventQuantiles@median)
if(any(event.pred <= 0) || any(event.pred > max.num.events)){
stop(paste("Invalid event.pred must be positive and < ",max.num.events+1,
". Fewer than ", 100*object@limit ,"% of the simulations had at least " ,max.num.events+1, " events.",sep=""))
}
if(!is.null(time.pred)){
time.pred <- FixDates(time.pred)
new.details <- PredictGivenDates(time.pred,object@eventQuantiles)
new.details$daysatrisk <- CalculateDaysAtRisk(object@singleSimDetails,new.details$time)
object@time.pred.data <- rbind(object@time.pred.data,new.details)
rownames(object@time.pred.data) <- NULL
}
if(!is.null(event.pred)){
new.details <- PredictGivenTargetEvents(event.pred,object@eventQuantiles)
new.details$daysatrisk <- CalculateDaysAtRisk(object@singleSimDetails,new.details$time)
object@event.pred.data <- rbind(object@event.pred.data,new.details)
rownames(object@event.pred.data) <- NULL
}
return(object)
})
##' @param round.method If the string "toMonths" then dates are rounded
##' to the nearest month. For the lower confidence interval value the month of
##' the date 15 days earlier than the given value is used
##' and for the upper confidence interval value the month of the
##' date 15 days later is used. For the median, the month is used.
##' @param text.width The width of the summary text
##' @param show.predictions Logical if TRUE then include the time.pred.data and
##' event.pred.data information in the text
##' @param show.at.risk Output the median number of at risk years
##' @rdname summary-methods
##' @name summary
##' @rdname summary-methods
##' @aliases summary,FromDataResults-method
##' @export
setMethod("summary","FromDataResults",
function(object,round.method="None",text.width=60,show.predictions=TRUE,show.at.risk=TRUE){
cat(getFromDataResultsSummaryText(object,round.method,text.width,show.predictions,show.at.risk))
})
##' @param title The title text, by default it is \code{summary(x)}
##' @param text.width Number of characters to wrap title text by.
##' @param show.obs If TRUE, add a line and points displaying the observed events.
##' @param round.method If the string "toMonths" then dates are rounded
##' to the nearest month. For the lower confidence interval value
##' the date 15 days earlier than the given value is rounded to the nearest
##' month and for the upper confidence intervalvalue the
##' date 15 dats later than the given value is rounded to the nearest month
##' @param show.predictions If TRUE show brown dashed lines at the user specified prediction
##' times/number of events.
##' @param pred.to.present If TRUE, move all predictions from past to present. Beware.
##' @param include.dropouts Include the cumulative dropouts on the graph (logical)
##' @param legend.position The position of the graph legend
##' @param custom.dates A vector of dates (in string or Date format) to be output on the x-axis
##' if NULL then default dates will be used
##' @rdname plot-methods
##' @name plot
##' @aliases plot,FromDataResults,missing-method
##' @export
setMethod( "plot",
signature( x="FromDataResults", y="missing" ),
function( x, title=getFromDataResultsSummaryText(x,round.method=round.method,text.width=text.width,
show.predictions=show.predictions),
show.title=FALSE, text.width=80, show.obs=FALSE,round.method="None",show.predictions=TRUE,
pred.to.present = FALSE, xlim = c(0,-1), ylim=NULL,include.dropouts=TRUE,
legend.position="bottomright",custom.dates=NULL) {
daysinyear <- standarddaysinyear()
#Note this function is due a refactoring
#as the rec, event and dropout lines could all call
#the same function and the
#event and dropout data could call the same function
if(pred.to.present){
warning("Using pred.to.present may mask problems with the data. This option is not recommended")
}
#First deal with margins
oldmar <- par()$mar
mar_val <- 0.5
if(show.title){
chr.pos <- which(unlist(strsplit(title,NULL)) == '\n')
chr.count <- length(chr.pos)
mar_val <- 1.5+chr.count
}
par(mar=c(5.1,4.1,mar_val,2.1))
#real data for past events
indat <- x@event.data@subject.data
indat$last.date <- LastDate(indat)
eventdata <- indat[indat$has.event==1, ]
eventdata <- eventdata[order(eventdata$last.date),]
dropoutdata <- indat[indat$withdrawn==1,]
dropoutdata <- dropoutdata[order(dropoutdata$last.date),]
inf.date <- as.Date(Inf,origin="1970-01-01")
q.median <- x@eventQuantiles@median[x@eventQuantiles@median!=inf.date]
q.upper <- x@eventQuantiles@upper[x@eventQuantiles@upper!=inf.date]
q.lower <- x@eventQuantiles@lower[x@eventQuantiles@lower!=inf.date]
#Sort out ranges
x_min <- min(x@recQuantiles@median) + xlim[1]*daysinyear/12
x_max <- if(xlim[2]>0) min(x@recQuantiles@median) + xlim[2]*daysinyear/12 else max(q.upper,q.median,q.lower)
r <- c(x_min,x_max)
N.subjects <- length(indat$rand.date)
if(pred.to.present && N.subjects > 0 && nrow(eventdata) > 0){
idx <- which(q.median < max(indat$last.date))
q.median[nrow(eventdata):max(idx)] <- as.Date(max(indat$last.date),origin="1970-01-01")
q.lower[idx] <- q.median[idx]
q.upper[idx] <- q.median[idx]
}
if(is.null(ylim)) ylim <- c(0, N.subjects + x@Naccrual)
plot(q.median, seq_along(q.median), type='l',
xlim=r,
ylim=ylim,
xlab="",
ylab="",
col="blue",
lwd = 2,
xaxt = "n",
las = 1
)
if(nrow(eventdata)> 0){
lines(eventdata$last.date, 1:nrow(eventdata), col="purple", lwd=2)
lines(c(tail(eventdata$last.date,1),max(indat$last.date)),rep(nrow(eventdata),2),col="purple",lwd=1,lty=1)
}
if(nrow(dropoutdata)>0 && include.dropouts){
lines(dropoutdata$last.date, 1:nrow(dropoutdata), col="tan", lwd=2 )
lines(c(tail(dropoutdata$last.date,1),max(indat$last.date)),rep(nrow(dropoutdata),2),col="tan",lwd=1,lty=1)
}
if(show.obs == TRUE){
if(nrow(eventdata) > 0) points( eventdata$last.date, 1:nrow(eventdata), col="purple", pch=20 )
if(nrow(dropoutdata)>0 && include.dropouts) points( dropoutdata$last.date, 1:nrow(dropoutdata), col="tan", pch=20 )
}
qs.mod <- if(is.null(custom.dates))
seq(from=r[1], to=r[2], by=(r[2]-r[1])/25 )
else
FixDates(custom.dates)
axis(1, qs.mod, format(qs.mod, "%d %b %Y"), cex.axis = .7, las=3)
mtext('N',side=2,at=median(seq_along(q.lower)),line=3, las=1)
lines(q.lower, seq_along(q.lower), type='l', lty='dashed', col="red", lwd = 2)
lines(q.upper, seq_along(q.upper), type='l', lty='dashed', col="red", lwd = 2)
lines(x@recQuantiles@median, 1:length( x@recQuantiles@median), lwd=2 )
lines(c(tail(x@recQuantiles@median,n=1),max(tail(x@recQuantiles@median,n=1),r[2])),rep(N.subjects+x@Naccrual,2),lwd=2)
lines(x@recQuantiles@lower, 1:length(x@recQuantiles@lower), lwd=1,lty="dashed")
lines(x@recQuantiles@upper, 1:length(x@recQuantiles@upper), lwd=1,lty="dashed")
if(include.dropouts && x@dropout.rate!=0){
lines(x@dropoutQuantiles@median,seq_along(x@dropoutQuantiles@median),type='l',col="aquamarine4",lwd=2)
lines(x@dropoutQuantiles@lower, 1:length(x@dropoutQuantiles@lower), lwd=1,lty="dashed",col="aquamarine3")
lines(x@dropoutQuantiles@upper, 1:length(x@dropoutQuantiles@upper), lwd=1,lty="dashed",col="aquamarine3")
}
if(nrow(eventdata)>0){
points(max(indat$last.date, na.rm=TRUE), nrow(eventdata), cex=1.5, pch=21, col="red", bg="yellow")
abline(h=nrow(eventdata), lty="dashed", col="blue")
}
abline(v=max(indat$last.date, na.rm=TRUE), lty="dashed", col="blue")
if(nrow(dropoutdata)>0){
points(max(indat$last.date, na.rm=TRUE), nrow(dropoutdata), cex=1.0, pch=21, col="tan", bg="darkslategray")
}
if(show.title==TRUE){
mtext(title,side=3,cex=0.9,adj=0)
}
if(nrow(x@event.pred.data)!=0 && show.predictions){
abline(v=x@event.pred.data$time, lty="dashed", col="brown")
abline(h=x@event.pred.data$event, lty="dashed", col="brown")
points(x@event.pred.data$time, x@event.pred.data$event, cex=1.5, pch=21, col="red", bg="yellow")
}
if(nrow(x@time.pred.data)!=0 && show.predictions){
abline(v=x@time.pred.data$time, lty="dashed", col="brown")
abline(h=x@time.pred.data$event, lty="dashed", col="brown")
points(x@time.pred.data$time, x@time.pred.data$event, cex=1.5, pch=21, col="red", bg="yellow")
}
#legend
CItext <- paste("CI [",x@limit,",",1-x@limit,"]",sep="")
leg.text <- c("Recruitment", "Predicted Events",CItext)
leg.col <- c("black","blue","red")
leg.lty <- c(1,1,8)
if(nrow(eventdata)>0){
leg.text <- c(leg.text,"Analysis Date")
leg.lty <- c(leg.lty,3)
leg.col <- c(leg.col,"blue")
}
if(show.predictions && (nrow(x@event.pred.data) > 0 || nrow(x@time.pred.data)>0) ){
leg.text <- c(leg.text,"Predictions")
leg.lty <- c(leg.lty,3)
leg.col <- c(leg.col,"brown")
}
if(include.dropouts && x@dropout.rate!=0){
leg.text <- c(leg.text,"Predicted Dropouts")
leg.lty <- c(leg.lty,1)
leg.col <- c(leg.col,"aquamarine4")
}
if(include.dropouts && x@dropout.rate==0 && sum(x@event.data@subject.data$withdrawn)!=0 ){
leg.text <- c(leg.text,"Dropouts")
leg.lty <- c(leg.lty,1)
leg.col <- c(leg.col,"tan")
}
legend(legend.position,
leg.text,col=leg.col,lty=leg.lty,text.col=leg.col,
lwd=rep(2,length(leg.text)),bty="n")
par(mar=oldmar)
})