context("Custom distributions in flexsurvreg")
## These previously didn't work when the d or h functions are
## defined in functions or testthat environments. To find the h or d
## function in form.dp, get() and exists() would need to look in
## parent.frame(2), i.e. the grandparent calling environment, but
## inherits=TRUE searches back through _enclosing_ (definition)
## environments.
## Even with d/h functions defined at top level, these still didn't
## work when called from R CMD check.
## Solve by adding dfns argument to flexsurvreg, passing functions through.
if (is.element("eha", installed.packages()[,1])) {
test_that("Custom distributions from another package",{
library(eha)
dllogis2 <- eha::dllogis; pllogis2 <- eha::pllogis
custom.llogis <- list(name="llogis2",
pars=c("shape","scale"),
location="scale",
transforms=c(log, log),
inv.transforms=c(exp, exp),
inits=function(t){ c(1, median(t)) })
fitll <- flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.llogis, dfns=list(d=dllogis2, p=pllogis2))
custom.ev <- list(name="EV",
pars=c("shape","scale"),
location="scale",
transforms=c(log, log),
inv.transforms=c(exp, exp),
inits=function(t){ c(1, median(t)) })
fitev <- flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.ev, dfns=list(d=dEV, p=pEV))
### h(x) = (b/a)(x/a)^(b-1)exp((x / a)^b)
### H(x) = exp( (x / a)^b) ) - 1
detach("package:eha")
fitll.builtin <- flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist="llogis")
expect_equal(fitll$loglik, fitll.builtin$loglik)
})
}
test_that("Custom distributions: hazard and cumulative hazard",{
hfoo <- function(x, rate=1){ rate }
Hfoo <- function(x, rate=1){ rate*x }
custom.foo <- list(name="foo", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp), inits=function(t)1/median(t))
fitf <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo))
fite <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist="exp")
expect_equal(fitf$loglik, fite$loglik)
})
test_that("Custom distributions: hazard only",{
hbar <- function(x, rate=1){ rate }
hbar <- Vectorize(hbar)
custom.bar <- list(name="bar", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp), inits=function(t)1/mean(t))
fitf <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.bar, dfns=list(h=hbar))
### FIXME q is Inf. is it Surv object bug? time2 being used
### it's trying to get p from exp(-H(t)) with t = Inf, should get
fite <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist="exp")
expect_equal(fitf$loglik, fite$loglik)
## with covariates. Approximation is less good. Many more integrations needed
fitf <- flexsurvreg(Surv(futime, fustat) ~ age, data = ovarian, dist=custom.bar, dfns=list(h=hbar))
fite <- flexsurvreg(Surv(futime, fustat) ~ age, data = ovarian, dist="exp")
expect_equal(fitf$loglik, fite$loglik, tolerance=1e-05)
## options to integrate()
flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.bar, dfns=list(h=hbar), integ.opts=list(rel.tol=0.01))
flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.bar, dfns=list(h=hbar), integ.opts=list(subdivisions=200))
## OK to omit inits from custom list if supply it to flexsurvreg
custom.bar <- list(name="bar", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp))
flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.bar, dfns=list(h=hbar), inits=0.001)
})
test_that("Custom distributions: density only",{
custom.baz <- list(name="baz", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp), inits=function(t)1/mean(t))
dbaz <- function(x, rate=1, log=FALSE){
if (log) {log(rate) - x*rate} else rate*exp(-rate*x)
}
dbaz <- Vectorize(dbaz)
fitf <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.baz, dfns=list(d=dbaz))
fite <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist="exp")
expect_equal(fitf$loglik, fite$loglik)
## with covariates
fitf <- flexsurvreg(Surv(futime, fustat) ~ age, data = ovarian, dist=custom.baz, dfns=list(d=dbaz), inits=c(9e-07, 0.12))
fite <- flexsurvreg(Surv(futime, fustat) ~ age, data = ovarian, dist="exp")
expect_equal(fitf$loglik, fite$loglik, tolerance=1e-05)
})
test_that("Custom distributions: summary", {
custom.baz <- list(name="baz", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp), inits=function(t)1/mean(t))
dbaz <- function(x, rate=1, log=FALSE){
if (log) {log(rate) - x*rate} else rate*exp(-rate*x)
}
dbaz <- Vectorize(dbaz)
fitd <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.baz, dfns=list(d=dbaz))
expect_no_error(summary(fitd, type='quantile'))
hfoo <- function(x, rate=1){ rate }
Hfoo <- function(x, rate=1){ rate*x }
custom.foo <- list(name="foo", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp), inits=function(t)1/median(t))
fith <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo))
expect_no_error(summary(fith, type='quantile'))
})
## Integration breaks for the Gompertz
if (0) {
hbar2 <- function(x, a=1, b=1){ b*exp(a*x) }
hbar2 <- Vectorize(hbar2)
custom.bar2 <- list(name="bar2", pars=c("a","b"), location="b", transforms=c(identity,log), inv.transforms=c(identity,exp), inits=function(t)c(0.001, 1/mean(t)))
fitf <- flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.bar2, control=list(trace=1,REPORT=1,reltol=1e-16,maxit=10000))
fitgo <- flexsurvreg(formula = Surv(futime, fustat) ~ 1,
data = ovarian, dist="gompertz",
control=list(trace=1,REPORT=1,reltol=1e-16))
}
## test_that("Custom distributions: hazard only, unknown function, more than one arg",{
## })
## TODO a more complicated one
test_that("Errors in custom distributions",{
hfoo <- function(x, rate=1){ rate }
Hfoo <- function(x, rate=1){ rate*x }
custom.foo <- list(pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"name\" element of custom distribution list not given")
custom.foo <- list(name=0, pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"name\" element of custom distribution list should be a string")
custom.foo <- list(name="foo", location="rate", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"parameter names \"pars\" not given")
custom.foo <- list(name="foo", pars=2, location="rate", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"parameter names \"pars\" should be a character vector")
custom.foo <- list(name="foo", pars="rate", transforms=c(log), inv.transforms=c(exp))
expect_warning(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo), fixedpars=TRUE, inits=1),
"location parameter not given, assuming it is the first one")
custom.foo <- list(name="foo", pars="rate", location="bar", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo), fixedpars=TRUE, inits=1),
"location parameter \"bar\" not in list of parameters")
custom.foo <- list(name="foo", pars=c("rate"), location="rate", transforms=c(log), inv.transforms=c(exp))
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"inits\" not supplied, and no function to estimate them found")
custom.foo <- list(name="foo", pars=c("rate"), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"transforms not given")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"transforms not given")
custom.foo <- list(name="foo", pars=c("rate"), transforms=log, inv.transforms=exp, location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"transforms\" must be a list")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log), inv.transforms=exp, location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"inv.transforms\" must be a list")
custom.foo <- list(name="foo", pars=c("rate"), transforms=list(2), inv.transforms=c(exp), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"some of \"transforms\" are not functions")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log), inv.transforms=list(2), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"some of \"inv.transforms\" are not functions")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log,log), inv.transforms=c(exp,exp), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"transforms vector of length 2, parameter names of length 1")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log), inv.transforms=c(exp,exp), location="rate")
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"inverse transforms vector of length 2, parameter names of length 1")
custom.foo <- list(name="foo", pars=c("rate"), transforms=c(log), inv.transforms=c(exp), location="rate", inits=1)
expect_error(flexsurvreg(Surv(futime, fustat) ~ 1, data = ovarian, dist=custom.foo, dfns=list(h=hfoo, H=Hfoo)),
"\"inits\" element of custom distribution list must be a function")
})
test_that("Errors in form.dp",{
expect_error(form.dp(dlist=list(), dfns=list()), "Neither density function .+ nor hazard function")
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.