Nothing
# Authors Mikis Stasinopoulos Bob Rigby and Vlasios Voudouris
# created 11-04-12
# upadated 8--6-14
#-------------------------------------------------------------------------------
# what is new June 2014
# i) the power transformation (x^p) function ptrans() now is defined to include
# zero as log(x)
# ii) the power transformation uses GAIC instead GD which was not reliable
# since different transformation will use differt effective df's
# iii) a prediction function for an lms object is created
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#This function is design to help the user to construct centile estimation.
#It is only applicable when only "one" explanatory variable is available
# (usually age).
#It stats by fitting a normal error distribution and smooth function for mu and
# then proceeds by fitting #several appropriate distributions.
# The set of gamlss.family distribution to fit are specified in the argument
# families.
#The default families arguments is LMS=c("BCCGo", "BCPEo", "BCTo") that is the
# LMS class of distributions.
#Note that this class is only appropriate when y is positive (with no zeros).
# If the response variable contains negative values and/or zeros then use
# the argument theSHASH theSHASH <- c("NO", "SHASHo") or add any other
# distribution which you think is appropriate
#-------------------------------------------------------------------------------
# the LMS familily of distributions
LMS <- c("BCCGo", "BCPEo", "BCTo")
# the SHASH
theSHASH <- c("NO", "SHASHo")
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
lms <- function(y, x,
families = LMS,
data = NULL,
k = 2, # for the AIC
cent = c(0.4, 2, 10, 25, 50, 75, 90, 98, 99.6), #100*pnorm((-4:4)*2/3)
calibration = TRUE,
trans.x = FALSE,
fix.power = NULL,
lim.trans = c(0, 1.5),
prof = FALSE,
step = 0.1,
legend = FALSE,
mu.df = NULL,
sigma.df = NULL,
nu.df = NULL,
tau.df = NULL,
c.crit = 0.01,
method.pb = c("ML", "GAIC"),
...
)
{
#-------------------------------------------------------------------------------
# local function
findPower <- function(y, x, data = NULL, lim.trans = c(0, 1.5), prof=FALSE, k=2, c.crit = 0.01, step=0.1)
{
cat("*** Checking for transformation for x ***", "\n")
ptrans<- function(x, p) if (abs(p)<=0.0001) log(x) else I(x^p)
fn <- function(p) GAIC(gamlss(y~pb(ptrans(x,p)), c.crit = c.crit, trace=FALSE), k=k)
if (prof) # profile dev
{
pp <- seq(lim.trans[1],lim.trans[2], step)
pdev <- rep(0, length(pp))
for (i in 1:length(pp))
{
pdev[i] <- fn(pp[i])
# cat(pp[i], pdev[i], "\n")
}
plot(pdev~pp, type="l")
points(pdev~pp,col="blue")
par <- pp[which.min(pdev)]
cat('*** power parameters ', par,"***"," \n")
} else
{
fn <- function(p) GAIC(gamlss(y~pb(ptrans(x,p)), c.crit = c.crit, trace=FALSE), k=k)
par <- optimise(fn, lower=lim.trans[1], upper=lim.trans[2])$minimum
cat('*** power parameters ', par,"***"," \n")
}
par
}
#-------------------------------------------------------------------------------
ptrans<- function(x, p) if (p==0) log(x) else I(x^p)
#-------------------------------------------------------------------------------
# end of local function
#-------------------------------------------------------------------------------
## the families to fit
FAM <- families
## which method
method.pb <- match.arg(method.pb)
## get the variables
ylab <- deparse(substitute(y))
xlab <- deparse(substitute(x))
y <- if (!is.null(data)) get(deparse(substitute(y)), envir=as.environment(data)) else y
x <- if (!is.null(data)) get(deparse(substitute(x)), envir=as.environment(data)) else x
## -----------------------------------------------------------------------------
## if need to check for transformation in x
if (is.null(fix.power))
{
if (trans.x) # if x^p
{
par <- findPower(y, x, lim.trans = lim.trans, prof=prof, k=k, c.crit = c.crit, step=0.1)
ox <- x
x <- ptrans(x,par)
}
} else
{ par <- fix.power
cat('*** power parameters fixed at ', par,"***"," \n")
ox <- x
x <- ptrans(x,par)
}
## starting model for fitted values for mu (we assuming that this will work).
## Note no sigma is fitted here
## fit the model --------------------------------------------------------------
cat('*** Initial fit***'," \n")
switch(method.pb,
"ML"= {m0 <- gamlss(y~pb(x), sigma.formula=~1, data=data, c.crit = 0.01)},
"GAIC"= {m0 <- gamlss(y~pb(x, method="GAIC", k=k), sigma.formula=~1, data=data, c.crit = 0.01)}) ## initial fit finish
## creating lists etc ----------------------------------------------------------
failed <- list()
fits <- list()
aic <- AIC(m0, k=k)
fits <- c(fits, aic)
whichdist <- 0
## fitting the diferent models in FAM ------------------------------------------
for (i in 1:length(FAM))
{
cat('*** Fitting', FAM[i], "***","\n")
switch(method.pb,
"ML"= { m1 <- try(gamlss(y ~ pb(x, df=mu.df),
sigma.formula = ~pb(x, df=sigma.df),
nu.formula = ~pb(x, df=nu.df),
tau.formula = ~pb(x, df=tau.df),
family = FAM[i], data = data,
...), silent=TRUE)}, #mu.start = fitted(m0),
"GAIC"= { m1 <- try(gamlss(y ~ pb(x, method="GAIC", k=k, df=mu.df),
sigma.formula = ~pb(x, method="GAIC", k=k, df=sigma.df),
nu.formula = ~pb(x, method="GAIC", k=k, df=nu.df),
tau.formula = ~pb(x, method="GAIC", k=k, df=tau.df),
family = FAM[i], data = data,
...), silent=TRUE)# mu.start = fitted(m0), taken out 11-05-17 Mikis
})
if (any(class(m1)%in%"try-error")) # if fitting failed
{
cat(FAM[i], " failed", "\n")
failed <- c(failed, FAM[i])
}
else
{
aic <- AIC(m1, k=k)
names(aic) <- FAM[i]
fits <- c(fits, aic)
if (AIC(m1, k=k) < AIC(m0, k=k))
{
m0 <-m1
whichdist <- i
}
}
}
if(whichdist==0)
{ # refitting the Normal with sigma if not of the models is any good
cat('*** Refitting', "NO", "***","\n")
m0 <- switch(method.pb,
"ML"= {m0 <- gamlss(y~pb(x), sigma.formula=~pb(x), data=data,
c.crit = 0.01)},
"GAIC"= {m0 <- gamlss(y~pb(x, method="GAIC", k=k),
sigma.formula=~pb(x),
data =data, c.crit = 0.01)}) ## initial fit finish
}
## changing the call t look better in the output -------------------------------
m0$call$mu.start <- NULL # this works OK
m0$call$data <- substitute(data) # this is OK
m0$call$family <- if(whichdist==0) "NO" else FAM[whichdist] # this is OK
if (is.null(mu.df)) m0$call$formula <- formula(y~pb(x))
#m0$call$formula[[2]] <- ylab
#m0$call$formula[[3]][[2]] <- xlab
if (is.null(sigma.df)) m0$call$sigma.formula <- formula(~pb(x))
if (is.null(nu.df)) m0$call$nu.formula <- formula(~pb(x))
if (is.null(tau.df)) m0$call$tau.formula <- formula(~pb(x))
# convert to string
stringCall <- toString(deparse(m0$call))
stringCall <- gsub("x", xlab, stringCall)
stringCall <- gsub("y", ylab, stringCall)
# convert bact to call
m0$call <- str2lang(stringCall)
# I am stack here
#m0$call$formula[3]
#if (is.null(mu.df))
# {m0$call$formula[[3]] <- sub("mu.df", "NULL", m0$call$formula[3])} else
# {m0$call$formula[[3]] <- sub("mu.df", mu.df, m0$call$formula[3])}
#
# FaM<-as.character(FAM[i])
# FaM
# m0$call$family <- substitute(Fam)
# m0$call
#
# sub("FAM[i]", as.character(FAM[i]), m0$call,)
## transformation needed -------------------------------------------------------
if (trans.x||!is.null(fix.power))
{
x <- ox
m0$power <- par
}
## save the rest information ---------------------------------------------------
m0$failed <- failed
fits <- unlist(fits)
m0$fits <- fits[order(fits)]
m0$xvar <- x#with(DaTa,x)
m0$y <- y#with(DaTa,y)
m0$ylab <- ylab
m0$xlab <- xlab
if (!is.null(data)) m0$call$data <- substitute(data)
## calibration -----------------------------------------------------------------
if (calibration)
{
calibration(m0, xvar=x, cent=cent, pch = 15, cex = 0.5, col = gray(0.7), ylab=ylab, xlab=xlab, legend=legend)
}
else
{
centiles(m0, xvar=x, cent=cent, pch = 15, cex = 0.5,
col = gray(0.7), ylab=ylab, xlab=xlab, legend=legend)
}
## saving the fitted functions for mu sigma nu and tau for prediction --------
if ("mu"%in%m0$par)
{
muFun <- splinefun(x, fitted(m0,"mu"), method="natural")
m0$muFun <- muFun
}
if ("sigma"%in%m0$par)
{
sigmaFun <- splinefun(x, fitted(m0,"sigma"), method="natural")
m0$sigmaFun <- sigmaFun
}
if ("nu"%in%m0$par)
{
nuFun <- splinefun(x, fitted(m0,"nu"), method="natural")
m0$nuFun <- nuFun
}
if ("tau"%in%m0$par)
{
tauFun <- splinefun(x, fitted(m0,"tau"), method="natural")
m0$tauFun <- tauFun
}
#------------------------------------------------------------------------------
# deparse((m0$call))
# toString(m0$call)
# toString(format(m0$call))
# toString(sprintf(format(m0$call)))
# toString(deparse((m1$call)))
# gsub("x", xlab, toString(deparse((m1$call))))
# str2lang(gsub("x", xlab, toString(deparse((m0$call)))))
class(m0) <- c("lms", class(m0))
m0 # save the last model
}
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# se ??
predict.lms <- function(object,
what = c("all","mu", "sigma", "nu", "tau"),
parameter= NULL,
newdata = NULL,
...
)
{
what <- if (!is.null(parameter)) {
match.arg(parameter, choices=c("mu", "sigma", "nu", "tau"))} else match.arg(what)
# if newdata is not null check the class
# if data.frame check for object$xlab
# other if vector use it
if (!is.null(newdata))
{
if (is(newdata,"data.frame"))
{
if (!object$xlab%in%names(newdata)) stop("the name in the data.frame do not much the x-variable in the model")
x <- newdata[[object$xlab]]
} else
{
x <- newdata
}
}
if (is.null(newdata))
{
out <- switch(what,
"all" = predictAll(object),
"mu" = fitted(object, "mu"),
"sigma" = fitted(object, "sigma"),
"nu" = fitted(object, "nu"),
"tau" = fitted(object, "tau"))
} else
{
if(what=="all")
{
out <- list()
if ("mu"%in%object$par)
{
mu <- object$muFun(x)
out$mu <- mu
}
if ("sigma"%in%object$par)
{
sigma <- object$sigmaFun(x)
out$sigma <- sigma
}
if ("nu"%in%object$par)
{
nu <- object$nuFun(x)
out$nu <- nu
}
if ("tau"%in%object$par)
{
tau <- object$tauFun(x)
out$tau <- tau
}
}
if(what=="mu") out <- object$muFun(x)
if(what=="sigma") out <- object$sigmaFun(x)
if(what=="nu") out <- object$nuFun(x)
if(what=="tau") out <- object$tauFun(x)
}
out
}
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# this function is appropriate to used when fitted model fails to c
calibration <- function(object, xvar, cent=c(0.4, 2, 10, 25, 50, 75, 90, 98, 99.6),#100*pnorm((-4:4)*2/3),
legend=FALSE, fan=FALSE, ...)
{
z <- quantile(resid(object), probs = cent/100)
p <- pNO(z, mu=0, sigma=1)
percent <- 100*p
if (fan)
{
centiles.fan(object, cent=percent, ...)
}
else
{
cc <- centiles(object, cent=percent, legend=legend, save=TRUE, ...)
cpp<-cbind(target=cent, calib.=cc[,1], sample=cc[,2])
print(cpp, digits=3)
}
}
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
z.scores <- function(object, y,x)
{
if (!is(object,"lms")) stop(paste("This is not an lms object", "\n", ""))
if (is.null(y)) stop("the y values should be set for z-scores")
if (is.null(x)) stop("the x values should be set for z-scores")
if (length(y)!= length(x)) stop("length of x and y is not the same")
pred <- predict(object, newdata=x)
fname <- object$family[1]
lpar <- length(object$par)
qfun <- paste("p",fname,sep="")
if(lpar==1)
{newcall <-call(qfun,y,mu=pred$mu) }
else if(lpar==2)
{newcall <-call(qfun,y, mu=pred$mu,sigma=pred$sigma) }
else if(lpar==3)
{newcall <-call(qfun,y,mu=pred$mu,sigma=pred$sigma,nu=pred$nu) }
else
{newcall <-call(qfun,y,mu=pred$mu,sigma=pred$sigma,nu=pred$nu,tau=pred$tau) }
cdf <- eval(newcall)
rqres <- qnorm(cdf)
rqres
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.