[f2e496]: / R / common.R

Download this file

153 lines (131 with data), 4.7 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
#Some miscellaneous functions used by both
#predict form parameters and predict from data
##' @importFrom stats uniroot
NULL
##' Return the number of days in the year
##'
##' This allows the user control over
##' whether the package uses 365.25, 365 (or any other number) of days
##' in a year.
##'
##' The number of days in a month is then set as daysinyear()/12
##'
##' @return The number of days in the year
##' @export
standarddaysinyear <- function() {
getOption('eventPrediction.daysinyear',
365.25)
}
# Round a number and force trailing zeros to be output
# @param number The number to be output
# @param dp The number of digits to display after the decimal point
# @return A string (e.g. "43.400")
roundForceOutputZeros <- function(number,dp){
if(dp < 1) {
stop("Invalid argument dp must be positive")
}
roundnumber <- as.character(round(number,digits=dp))
outputdp <- nchar(strsplit(as.character(roundnumber),"\\.")[[1]][2])
zeros <- rep("0",dp-outputdp)
return(paste(roundnumber,paste(zeros,collapse=""),sep=""))
}
# Calculate the number of subjects on each arm
#
# \code{floor((r/(r+1))*N)} are allocated to the experimental arm
# the rest are allocated ot the control arm
#
# @param singleArm logical TRUE if study is a single arm
# @param r Allocation ratio, see Study object
# @param N Total number of subjects on the trial
# @return A vector (N_control,N_experimental)
getNs <- function(singleArm,r,N){
if (singleArm){
return(c(N,0))
}
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
oldres <- (r/(r+1))*N
res <- if(!is.wholenumber(oldres)) floor(oldres) else oldres
res <- c(N-res,res)
if(any(res==0)){
stop("Too few subjects recruited for given randomization balance
All subjects would be recruited onto the same arm.")
}
return(res)
}
# Add line breaks to a string
# @param title text to add line breaks to
# @param text.width Target number of characters per row
# @return text with line breaks
AddLineBreaks <- function( title, text.width ) {
wrapper <- function(x, ... ) paste(strwrap(x, ... ) )
wtext <- wrapper(title, width = text.width )
return(paste(wtext,collapse="\n"))
}
##' Function which attempts to read in a csv file
##' picking a delimiter from a given set of options
##'
##' The function works by counting the number of occurences
##' of each delimiter on each line and for exactly one
##' of the delimiter options all lines contain the same number
##' of occurences (>0) then this delimiter is used
##'
##' @param path The path to the csv file to be read
##' @param delim_options A vector of characters from which the
##' delimiter should be chosen
##' @return If successful a data frame containing the csv file
##' if unsuccessful an error is thrown
##' @export
csvSniffer <- function(path,delim_options=c(',',';','\t')){
#currently reading file twice ought to be improved
vec <- readLines(con=path)
#remove empty lines
vec <- vec[sapply(vec, nchar) > 0]
ans <- sapply(delim_options,function(x){
a <- unlist(lapply(vec,function(y)sum(unlist(strsplit(y,split=""))==x)))
if(all(a==a[1]) && a[1] != 0) TRUE else FALSE
})
if(sum(ans) != 1){
stop("Cannot determine delimiter")
}
read.csv(path,sep=names(ans[ans==TRUE]))
}
##' Given trial assumptions describing an exponential model
##' Use the method of moments to fit a single Weibull distribution
##'
##' See, for example, Lei, Y. Evaluation of three methods for estimating the Weibull distribution
##' parameters of Chinese pine (Pinus tabulaeformis). Journal of Forest Science 54.12 (2008): 566-571.
##'
##' @param HR Hazard ratio
##' @param r Randomization balance
##' @param M control arm median
##' @export
FitMixtureModel <- function(HR,r,M){
lapply(list(HR=HR,r=r,M=M),function(x){
if(!is.numeric(x) || x <= 0 || length(x)!=1){
stop("All arguments to FitMixtureModel must be numeric, positive and of length 1")
}
})
ml2 <- M/log(2)
mu <- (ml2*(1+r/HR))/(r+1) # = E(control)/(r+1) + rE(active)/r+1
sigma <- (ml2/(1+r)) * sqrt(1+2*r-2*r/HR + (r*(r+2))/(HR*HR))
return(RootFindRateShape(mu,sigma))
}
# Fit shape and rate given mean and sd of Weibull
# distribution
#
# @param mu mean of Weibull
# @param sigma sd of distribution
RootFindRateShape <- function(mu,sigma){
f <- function(x){
sigma/mu - sqrt(gamma(1+2/x) - gamma(1+1/x)^2)/gamma(1+1/x)
}
shape <- tryCatch({
uniroot(f,c(0.1,10))$root
},error=function(cond){
warning(paste("Error fitting shape:",cond,"Returning NA"))
return(list(rate=NA,shape=NA))
}
)
rate <- gamma(1+1/shape)/mu
return(list(rate=rate,shape=shape))
}