
Quantile Function of Piecewise Exponential Distribution
Source:R/qPiecewiseExponential.R
qPiecewiseExponential.RdTo generate endpoint that follows a piecewise exponential distribution and
is correlated with other endpoints, the copula method is commonly used. The
quantile function needs to be specified (e.g., in the simdata package).
If a piecewise exponential distributed endpoint is independent to other
endpoints, one can simply use
TrialSimulator::PiecewiseConstantExponentialRNG()
to specify the generator argument in endpoint().
There are many R packages implementing the quantile function of the
piecewise exponential distributed random variable. Why do I implement it
again? The reason is that this function is extremely important for simulating
time-to-event endpoint in clinical trial simulation, thus the speed matters.
qPiecewiseExponential() is implemented purely in R for
code transparency, and is much faster than other packages.
Arguments
- p
numeric. A vector of probabilities.
- times
numeric. A vector of time points where risk (event rates) change. 0 shouldn't be in
times.- piecewise_risk
numeric. A vector of constant risk (event rates) in a time window.
length(piecewise_risk) = length(times) + 1. To fully specify a piecewise exponential distribution, the number of risk parameters is one greater than the number of changepoints intimes.
Examples
## This code snippet can take > 10s to execute
if(interactive()){
library(TrialSimulator)
run <- TRUE
if(!requireNamespace("rpact", quietly = TRUE)){
run <- FALSE
message("Please install 'rpact' to run this example.")
}
if(!requireNamespace("PWEXP", quietly = TRUE)){
run <- FALSE
message("Please install 'PWEXP' to run this example.")
}
if(!requireNamespace("PWEALL", quietly = TRUE)){
run <- FALSE
message("Please install 'PWEALL' to run this example.")
}
if(run){
x <- solvePiecewiseConstantExponentialDistribution(
surv_prob = c(.9, .75, .64, .42, .28),
times = c(.4, 1.2, 4, 5.5, 9)
)
p <- stats::runif(1e5)
## fast, and only five lines of R codes
message('TrialSimulator::qPiecewiseExponential(): ')
system.time(
a <- qPiecewiseExponential(
p, times = x$end_time, piecewise_risk = c(x$piecewise_risk, .1)
)
) |> print()
## > 10s
message('rpact::getPiecewiseExponentialQuantile(): ')
system.time(
b <- rpact::getPiecewiseExponentialQuantile(
p, piecewiseSurvivalTime = c(0, x$end_time),
piecewiseLambda=c(x$piecewise_risk, .1)
)
) |> print()
## equally fast, but implemented in Fortran
message('PWEALL::qpwe(): ')
system.time(
c <- PWEALL::qpwe(p, rate = c(x$piecewise_risk, .1), tchange = c(0, x$end_time))$q
) |> print()
## equally fast, long codes in R (maybe more versatile?)
message('PWEXP::qpwexp(): ')
system.time(
d <- PWEXP::qpwexp(p, rate = c(x$piecewise_risk, .1), breakpoint = x$end_time)
) |> print()
message('a == b: ')
all.equal(a, b) |> print()
message('a == c: ')
all.equal(a, c) |> print()
message('a == d: ')
all.equal(a, d) |> print()
}
}