Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files
ExWALD.R
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#' The Ex-Wald family
|
| 2 |
+
#'
|
| 3 |
+
#' @author Freddy Hernandez, \email{fhernanb@unal.edu.co}
|
| 4 |
+
#'
|
| 5 |
+
#' @description
|
| 6 |
+
#' The function \code{ExWALD()} defines the Ex-wALD distribution, three-parameter
|
| 7 |
+
#' continuous distribution for a \code{gamlss.family} object to be used in
|
| 8 |
+
#' GAMLSS fitting using the function \code{gamlss()}.
|
| 9 |
+
#'
|
| 10 |
+
#' @param mu.link defines the mu.link, with "log" link as the default for the mu parameter.
|
| 11 |
+
#' @param sigma.link defines the sigma.link, with "log" link as the default for the sigma parameter.
|
| 12 |
+
#' @param nu.link defines the nu.link, with "log" link as the default for the nu parameter.
|
| 13 |
+
#'
|
| 14 |
+
#' @references
|
| 15 |
+
#' Schwarz, W. (2001). The ex-Wald distribution as a descriptive model
|
| 16 |
+
#' of response times. Behavior Research Methods,
|
| 17 |
+
#' Instruments, & Computers, 33, 457-469.
|
| 18 |
+
#'
|
| 19 |
+
#' Heathcote, A. (2004). Fitting Wald and ex-Wald distributions to
|
| 20 |
+
#' response time data: An example using functions for the S-PLUS package.
|
| 21 |
+
#' Behavior Research Methods, Instruments, & Computers, 36, 678-694.
|
| 22 |
+
#'
|
| 23 |
+
#' @seealso \link{dExWALD}.
|
| 24 |
+
#'
|
| 25 |
+
#' @details
|
| 26 |
+
#' The Ex-Wald distribution with parameters \eqn{\mu}, \eqn{\sigma}
|
| 27 |
+
#' and \eqn{\nu} has density given by
|
| 28 |
+
#'
|
| 29 |
+
#' \eqn{f(x |\mu, \sigma, \nu) = \frac{1}{\nu} \exp(\frac{-x}{\nu} + \sigma(\mu-k)) F_W(x|k, \sigma) \, \text{for} \, k \geq 0}
|
| 30 |
+
#'
|
| 31 |
+
#' \eqn{f(x |\mu, \sigma, \nu) = \frac{1}{\nu} \exp\left( \frac{-(\sigma-\mu)^2}{2x} \right) Re \left( w(k^\prime \sqrt{x/2} + \frac{\sigma i}{\sqrt{2x}}) \right) \, \text{for} \, k < 0}
|
| 32 |
+
#'
|
| 33 |
+
#' where \eqn{k=\sqrt{\mu^2-\frac{2}{\nu}}},
|
| 34 |
+
#' \eqn{k^\prime=\sqrt{\frac{2}{\nu}-\mu^2}} and
|
| 35 |
+
#' \eqn{F_W} corresponds to the cumulative function of
|
| 36 |
+
#' the Wald distribution.
|
| 37 |
+
#'
|
| 38 |
+
#' More details about those expressions
|
| 39 |
+
#' can be found on page 680 from Heathcote (2004).
|
| 40 |
+
#'
|
| 41 |
+
#' @returns Returns a gamlss.family object which can be used to fit a
|
| 42 |
+
#' Ex-WALD distribution in the \code{gamlss()} function.
|
| 43 |
+
#'
|
| 44 |
+
#' @example examples/examples_ExWALD.R
|
| 45 |
+
#'
|
| 46 |
+
#' @importFrom gamlss.dist checklink
|
| 47 |
+
#' @importFrom gamlss rqres.plot
|
| 48 |
+
#' @export
|
| 49 |
+
ExWALD <- function(mu.link="log",
|
| 50 |
+
sigma.link="log",
|
| 51 |
+
nu.link="log") {
|
| 52 |
+
|
| 53 |
+
mstats <- checklink("mu.link", "Ex-Wald",
|
| 54 |
+
substitute(mu.link), c("log"))
|
| 55 |
+
dstats <- checklink("sigma.link", "Ex-Wald",
|
| 56 |
+
substitute(sigma.link), c("log"))
|
| 57 |
+
vstats <- checklink("nu.link", "Ex-Wald",
|
| 58 |
+
substitute(nu.link), c("log"))
|
| 59 |
+
|
| 60 |
+
structure(list(family = c("ExWALD", "Ex-Wald"),
|
| 61 |
+
parameters = list(mu=TRUE, sigma=TRUE, nu=TRUE),
|
| 62 |
+
nopar = 3,
|
| 63 |
+
type = "Continuous",
|
| 64 |
+
|
| 65 |
+
mu.link = as.character(substitute(mu.link)),
|
| 66 |
+
sigma.link = as.character(substitute(sigma.link)),
|
| 67 |
+
nu.link = as.character(substitute(nu.link)),
|
| 68 |
+
|
| 69 |
+
mu.linkfun = mstats$linkfun,
|
| 70 |
+
sigma.linkfun = dstats$linkfun,
|
| 71 |
+
nu.linkfun = vstats$linkfun,
|
| 72 |
+
|
| 73 |
+
mu.linkinv = mstats$linkinv,
|
| 74 |
+
sigma.linkinv = dstats$linkinv,
|
| 75 |
+
nu.linkinv = vstats$linkinv,
|
| 76 |
+
|
| 77 |
+
mu.dr = mstats$mu.eta,
|
| 78 |
+
sigma.dr = dstats$mu.eta,
|
| 79 |
+
nu.dr = vstats$mu.eta,
|
| 80 |
+
|
| 81 |
+
# First derivates
|
| 82 |
+
|
| 83 |
+
dldm = function(y, mu, sigma, nu) {
|
| 84 |
+
dm <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 85 |
+
theta="mu",
|
| 86 |
+
delta=0.001)
|
| 87 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 88 |
+
dldm
|
| 89 |
+
},
|
| 90 |
+
|
| 91 |
+
dldd = function(y, mu, sigma, nu) {
|
| 92 |
+
dd <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 93 |
+
theta="sigma",
|
| 94 |
+
delta=0.001)
|
| 95 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 96 |
+
dldd
|
| 97 |
+
},
|
| 98 |
+
|
| 99 |
+
dldv = function(y, mu, sigma, nu) {
|
| 100 |
+
dv <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 101 |
+
theta="nu",
|
| 102 |
+
delta=0.001)
|
| 103 |
+
dldv <- as.vector(attr(dv, "gradient"))
|
| 104 |
+
dldv
|
| 105 |
+
},
|
| 106 |
+
|
| 107 |
+
# Second derivates
|
| 108 |
+
|
| 109 |
+
d2ldm2 = function(y, mu, sigma, nu) {
|
| 110 |
+
dm <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 111 |
+
theta="mu",
|
| 112 |
+
delta=0.001)
|
| 113 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 114 |
+
d2ldm2 <- - dldm*dldm
|
| 115 |
+
d2ldm2 <- ifelse(d2ldm2 < -1e-15, d2ldm2, -1e-15)
|
| 116 |
+
d2ldm2
|
| 117 |
+
},
|
| 118 |
+
|
| 119 |
+
d2ldmdd = function(y, mu, sigma, nu) {
|
| 120 |
+
dm <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 121 |
+
theta="mu",
|
| 122 |
+
delta=0.001)
|
| 123 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 124 |
+
dd <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 125 |
+
theta="sigma",
|
| 126 |
+
delta=0.001)
|
| 127 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 128 |
+
d2ldmdd <- - dldm*dldd
|
| 129 |
+
d2ldmdd <- ifelse(d2ldmdd < -1e-15, d2ldmdd, -1e-15)
|
| 130 |
+
d2ldmdd
|
| 131 |
+
},
|
| 132 |
+
|
| 133 |
+
d2ldmdv = function(y, mu, sigma, nu) {
|
| 134 |
+
dm <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 135 |
+
theta="mu",
|
| 136 |
+
delta=0.001)
|
| 137 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 138 |
+
dv <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 139 |
+
theta="nu",
|
| 140 |
+
delta=0.001)
|
| 141 |
+
dldv <- as.vector(attr(dv, "gradient"))
|
| 142 |
+
d2ldmdv <- - dldm*dldv
|
| 143 |
+
d2ldmdv <- ifelse(d2ldmdv < -1e-15, d2ldmdv, -1e-15)
|
| 144 |
+
d2ldmdv
|
| 145 |
+
},
|
| 146 |
+
|
| 147 |
+
d2ldd2 = function(y, mu, sigma, nu) {
|
| 148 |
+
dd <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 149 |
+
theta="sigma",
|
| 150 |
+
delta=0.001)
|
| 151 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 152 |
+
d2ldd2 <- - dldd*dldd
|
| 153 |
+
d2ldd2 <- ifelse(d2ldd2 < -1e-15, d2ldd2, -1e-15)
|
| 154 |
+
d2ldd2
|
| 155 |
+
},
|
| 156 |
+
|
| 157 |
+
d2ldddv = function(y, mu, sigma, nu) {
|
| 158 |
+
dd <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 159 |
+
theta="sigma",
|
| 160 |
+
delta=0.001)
|
| 161 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 162 |
+
dv <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 163 |
+
theta="nu",
|
| 164 |
+
delta=0.001)
|
| 165 |
+
dldv <- as.vector(attr(dv, "gradient"))
|
| 166 |
+
d2ldddv <- - dldd*dldv
|
| 167 |
+
d2ldddv <- ifelse(d2ldddv < -1e-15, d2ldddv, -1e-15)
|
| 168 |
+
d2ldddv
|
| 169 |
+
},
|
| 170 |
+
|
| 171 |
+
d2ldv2 = function(y, mu, sigma, nu) {
|
| 172 |
+
dv <- gamlss::numeric.deriv(dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 173 |
+
theta="nu",
|
| 174 |
+
delta=0.001)
|
| 175 |
+
dldv <- as.vector(attr(dv, "gradient"))
|
| 176 |
+
d2ldv2 <- - dldv*dldv
|
| 177 |
+
d2ldv2 <- ifelse(d2ldv2 < -1e-15, d2ldv2, -1e-15)
|
| 178 |
+
d2ldv2
|
| 179 |
+
},
|
| 180 |
+
|
| 181 |
+
G.dev.incr = function(y, mu, sigma, nu, ...) -2*dExWALD(y, mu, sigma, nu, log=TRUE),
|
| 182 |
+
rqres = expression(rqres(pfun="pExWALD", type="Continuous", y=y, mu=mu, sigma=sigma, nu=nu)),
|
| 183 |
+
|
| 184 |
+
mu.initial = expression(mu <- rep(fitexw(y)[1], length(y))),
|
| 185 |
+
sigma.initial = expression(sigma <- rep(fitexw(y)[2], length(y))),
|
| 186 |
+
nu.initial = expression(nu <- rep(fitexw(y)[3], length(y))),
|
| 187 |
+
|
| 188 |
+
mu.valid = function(mu) all(mu > 0),
|
| 189 |
+
sigma.valid = function(sigma) all(sigma > 0),
|
| 190 |
+
nu.valid = function(nu) all(nu > 0),
|
| 191 |
+
|
| 192 |
+
y.valid = function(y) all(y > 0),
|
| 193 |
+
|
| 194 |
+
mean = function(mu, sigma, nu) {nu + sigma/mu},
|
| 195 |
+
variance = function(mu, sigma, nu) {nu^2 + sigma/mu^3}
|
| 196 |
+
),
|
| 197 |
+
class = c("gamlss.family", "family"))
|
| 198 |
+
}
|
| 199 |
+
#' Auxiliar function for the Ex-Wald distribution
|
| 200 |
+
#' @description This function generates start values.
|
| 201 |
+
#' @param x a value for x.
|
| 202 |
+
#' @param p a value for p.
|
| 203 |
+
#' @return returns a vector with starting values.
|
| 204 |
+
#' @keywords internal
|
| 205 |
+
#' @importFrom stats sd var
|
| 206 |
+
#' @export
|
| 207 |
+
exwstpt <- function(x, p=0.5) {
|
| 208 |
+
t <- p*sd(x)
|
| 209 |
+
m <- sqrt((mean(x)-t)/(var(x)-t^2))
|
| 210 |
+
a <- m*(mean(x)-t)
|
| 211 |
+
res <- c(m, a, t)
|
| 212 |
+
return(res)
|
| 213 |
+
}
|
| 214 |
+
#' Auxiliar pwald function for the Ex-Wald distribution
|
| 215 |
+
#' @description This function emulates the pWALD function.
|
| 216 |
+
#' @param w a value for w.
|
| 217 |
+
#' @param m a value for m.
|
| 218 |
+
#' @param a a value for a.
|
| 219 |
+
#' @param s a value for s.
|
| 220 |
+
#' @return returns a vector with cumulative probabilities.
|
| 221 |
+
#' @keywords internal
|
| 222 |
+
#' @export
|
| 223 |
+
pwald <- function(w, m, a, s=0) {
|
| 224 |
+
w <- w - s;
|
| 225 |
+
sqrtw <- sqrt(w);
|
| 226 |
+
k1 <- (m*w-a)/sqrtw;
|
| 227 |
+
k2 <- (m*w+a)/sqrtw
|
| 228 |
+
p1 <- exp(2*a*m);
|
| 229 |
+
p2 <- pnorm(-k2);
|
| 230 |
+
bad <- (p1==Inf) | (p2==0);
|
| 231 |
+
p <- p1*p2
|
| 232 |
+
p[bad] <- (exp(-(k1[bad]^2)/2 - 0.94/(k2[bad]^2))/(k2[bad]*((2*pi)^.5)))
|
| 233 |
+
p + pnorm(k1)
|
| 234 |
+
}
|
| 235 |
+
#' Auxiliar function to generate random values for Ex-Wald distribution
|
| 236 |
+
#' @description This function generates another form to generate values.
|
| 237 |
+
#' @param x a value for x.
|
| 238 |
+
#' @param y a value for y.
|
| 239 |
+
#' @return returns a vector with values.
|
| 240 |
+
#' @keywords internal
|
| 241 |
+
#' @export
|
| 242 |
+
rew <- function(x, y) {
|
| 243 |
+
uv <- uandv(y, x)
|
| 244 |
+
exp(y^2-x^2)*(cos(2*x*y)*(1-uv[,1])+sin(2*x*y)*uv[,2])
|
| 245 |
+
}
|
| 246 |
+
#' Auxiliar den_exw function for the Ex-Wald distribution
|
| 247 |
+
#' @description This function emulates the dExWALD function.
|
| 248 |
+
#' @param r value for r.
|
| 249 |
+
#' @param m value for m.
|
| 250 |
+
#' @param a value for a.
|
| 251 |
+
#' @param t value for t.
|
| 252 |
+
#' @return returns a vector with probabilities.
|
| 253 |
+
#' @keywords internal
|
| 254 |
+
#' @export
|
| 255 |
+
den_exw <- function(r, m, a, t) {
|
| 256 |
+
k <- (m^2 - (2/t))
|
| 257 |
+
if (k < 0) {
|
| 258 |
+
res <- exp(m*a - (a^2)/(2*r) - r*(m^2)/2)*
|
| 259 |
+
rew(sqrt(-r*k/2), a/sqrt(2*r))/t
|
| 260 |
+
} else {
|
| 261 |
+
k <- sqrt(k)
|
| 262 |
+
res <- pwald(r,k,a)*exp(a*(m-k) - (r/t))/t
|
| 263 |
+
}
|
| 264 |
+
return(res)
|
| 265 |
+
}
|
| 266 |
+
#' Auxiliar function to obtain minus loglik for Ex-Wald
|
| 267 |
+
#' @description This function calculates minus loglik.
|
| 268 |
+
#' @param p a vector with the parameters.
|
| 269 |
+
#' @param x a vector with the random sample.
|
| 270 |
+
#' @return returns the minus loglik.
|
| 271 |
+
#' @keywords internal
|
| 272 |
+
#' @export
|
| 273 |
+
negllexw <- function(p, x) {
|
| 274 |
+
-sum(log(den_exw(x, p[1], p[2], p[3])))
|
| 275 |
+
}
|
| 276 |
+
#' Auxiliar function for the Ex-Wald distribution
|
| 277 |
+
#' @description This function generates starting values.
|
| 278 |
+
#' @param rt a vector with the random sample.
|
| 279 |
+
#' @param p a value for p.
|
| 280 |
+
#' @param start an optional start vector.
|
| 281 |
+
#' @param scaleit logical value to scale.
|
| 282 |
+
#' @return returns a vector with cumulative probabilities.
|
| 283 |
+
#' @keywords internal
|
| 284 |
+
#' @importFrom stats nlminb
|
| 285 |
+
#' @export
|
| 286 |
+
fitexw <- function(rt, p=0.5,
|
| 287 |
+
start=exwstpt(rt, p),
|
| 288 |
+
scaleit=TRUE){
|
| 289 |
+
if (scaleit)
|
| 290 |
+
fit <- nlminb(start=start,
|
| 291 |
+
lower=c(1e-8, 1e-8, 1),
|
| 292 |
+
objective=negllexw,
|
| 293 |
+
x=rt,
|
| 294 |
+
scale=(1/start),
|
| 295 |
+
control=list(eval.max=400, iter.max=300))
|
| 296 |
+
else
|
| 297 |
+
fit <- nlminb(start=start,
|
| 298 |
+
lower=c(1e-8, 1e-8, 1),
|
| 299 |
+
objective=negllexw,
|
| 300 |
+
x=rt,
|
| 301 |
+
control=list(eval.max=400, iter.max=300,
|
| 302 |
+
scale.tol=1e-8))
|
| 303 |
+
|
| 304 |
+
return(fit$par)
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
|
WALD.R
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#' The Wald family
|
| 2 |
+
#'
|
| 3 |
+
#' @author Sofia Cuartas Garc铆a, \email{scuartasg@unal.edu.co}
|
| 4 |
+
#'
|
| 5 |
+
#' @description
|
| 6 |
+
#' The function \code{WALD()} defines the wALD distribution, two-parameter
|
| 7 |
+
#' continuous distribution for a \code{gamlss.family} object to be used in GAMLSS fitting
|
| 8 |
+
#' using the function \code{gamlss()}.
|
| 9 |
+
#'
|
| 10 |
+
#' @param mu.link defines the mu.link, with "log" link as the default for the mu parameter.
|
| 11 |
+
#' @param sigma.link defines the sigma.link, with "log" link as the default for the sigma parameter.
|
| 12 |
+
#'
|
| 13 |
+
#' @references
|
| 14 |
+
#' Heathcote, A. (2004). Fitting Wald and ex-Wald distributions to
|
| 15 |
+
#' response time data: An example using functions for the S-PLUS package.
|
| 16 |
+
#' Behavior Research Methods, Instruments, & Computers, 36, 678-694.
|
| 17 |
+
#'
|
| 18 |
+
#' @seealso \link{dWALD}.
|
| 19 |
+
#'
|
| 20 |
+
#' @details
|
| 21 |
+
#' The Wald distribution with parameters \eqn{\mu} and \eqn{sigma} has density given by
|
| 22 |
+
#'
|
| 23 |
+
#' \eqn{\operatorname{f}(x |\mu, \sigma)=\frac{\sigma}{\sqrt{2 \pi x^3}} \exp \left[-\frac{(\sigma-\mu x)^2}{2x}\right ], x>0 }
|
| 24 |
+
#'
|
| 25 |
+
#' @returns Returns a gamlss.family object which can be used to fit a WALD distribution in the \code{gamlss()} function.
|
| 26 |
+
#'
|
| 27 |
+
#' @example examples/examples_WALD.R
|
| 28 |
+
#'
|
| 29 |
+
#' @importFrom gamlss.dist checklink
|
| 30 |
+
#' @importFrom gamlss rqres.plot
|
| 31 |
+
#' @export
|
| 32 |
+
WALD <- function (mu.link="log", sigma.link="log"){
|
| 33 |
+
mstats <- checklink("mu.link", "WALD",
|
| 34 |
+
substitute(mu.link),
|
| 35 |
+
c("log", "own"))
|
| 36 |
+
dstats <- checklink("sigma.link", "WALD",
|
| 37 |
+
substitute(sigma.link),
|
| 38 |
+
c("log", "own"))
|
| 39 |
+
|
| 40 |
+
structure(list(family=c("WALD", "Wald"),
|
| 41 |
+
parameters=list(mu=TRUE, sigma=TRUE),
|
| 42 |
+
nopar=2,
|
| 43 |
+
type="Continuous",
|
| 44 |
+
|
| 45 |
+
mu.link = as.character(substitute(mu.link)),
|
| 46 |
+
sigma.link = as.character(substitute(sigma.link)),
|
| 47 |
+
|
| 48 |
+
mu.linkfun = mstats$linkfun,
|
| 49 |
+
sigma.linkfun = dstats$linkfun,
|
| 50 |
+
|
| 51 |
+
mu.linkinv = mstats$linkinv,
|
| 52 |
+
sigma.linkinv = dstats$linkinv,
|
| 53 |
+
|
| 54 |
+
mu.dr = mstats$mu.eta,
|
| 55 |
+
sigma.dr = dstats$mu.eta,
|
| 56 |
+
|
| 57 |
+
# First derivates
|
| 58 |
+
dldm = function(y, mu, sigma) {
|
| 59 |
+
dldm <- sigma-mu*y
|
| 60 |
+
dldm
|
| 61 |
+
},
|
| 62 |
+
|
| 63 |
+
dldd = function(y, mu, sigma) {
|
| 64 |
+
dldd <- 1/sigma - (sigma-mu*y)/y
|
| 65 |
+
dldd
|
| 66 |
+
},
|
| 67 |
+
|
| 68 |
+
# Second derivates
|
| 69 |
+
d2ldm2 = function(y, mu, sigma) {
|
| 70 |
+
dm <- gamlss::numeric.deriv(dWALD(y, mu, sigma, log=TRUE),
|
| 71 |
+
theta="mu",
|
| 72 |
+
delta=0.0001)
|
| 73 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 74 |
+
d2ldm2 <- - dldm * dldm
|
| 75 |
+
d2ldm2 <- ifelse(d2ldm2 < -1e-15, d2ldm2, -1e-15)
|
| 76 |
+
d2ldm2
|
| 77 |
+
},
|
| 78 |
+
|
| 79 |
+
d2ldmdd = function(y, mu, sigma) {
|
| 80 |
+
dm <- gamlss::numeric.deriv(dWALD(y, mu, sigma, log=TRUE),
|
| 81 |
+
theta="mu",
|
| 82 |
+
delta=0.0001)
|
| 83 |
+
dldm <- as.vector(attr(dm, "gradient"))
|
| 84 |
+
dd <- gamlss::numeric.deriv(dWALD(y, mu, sigma, log=TRUE),
|
| 85 |
+
theta="sigma",
|
| 86 |
+
delta=0.0001)
|
| 87 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 88 |
+
d2ldmdd <- - dldm * dldd
|
| 89 |
+
d2ldmdd <- ifelse(d2ldmdd < -1e-15, d2ldmdd, -1e-15)
|
| 90 |
+
d2ldmdd
|
| 91 |
+
},
|
| 92 |
+
|
| 93 |
+
d2ldd2 = function(y, mu, sigma) {
|
| 94 |
+
dd <- gamlss::numeric.deriv(dWALD(y, mu, sigma, log=TRUE),
|
| 95 |
+
theta="sigma",
|
| 96 |
+
delta=0.0001)
|
| 97 |
+
dldd <- as.vector(attr(dd, "gradient"))
|
| 98 |
+
d2ldd2 <- - dldd * dldd
|
| 99 |
+
d2ldd2 <- ifelse(d2ldd2 < -1e-15, d2ldd2, -1e-15)
|
| 100 |
+
d2ldd2
|
| 101 |
+
},
|
| 102 |
+
|
| 103 |
+
G.dev.incr = function(y, mu, sigma, pw = 1, ...) -2*dWALD(y, mu, sigma, log=TRUE),
|
| 104 |
+
rqres = expression(rqres(pfun="pWALD", type="Continuous", y=y, mu=mu, sigma=sigma)),
|
| 105 |
+
|
| 106 |
+
mu.initial = expression(mu <- rep(wald_start(y)[1], length(y)) ),
|
| 107 |
+
sigma.initial = expression(sigma <- rep(wald_start(y)[2], length(y)) ),
|
| 108 |
+
|
| 109 |
+
mu.valid = function(mu) all(mu > 0),
|
| 110 |
+
sigma.valid = function(sigma) all(sigma > 0),
|
| 111 |
+
|
| 112 |
+
y.valid = function(y) all(y > 0),
|
| 113 |
+
|
| 114 |
+
mean = function(mu, sigma) sigma/mu,
|
| 115 |
+
variance = function(mu, sigma) sigma/(mu^3)
|
| 116 |
+
),
|
| 117 |
+
class=c("gamlss.family", "family"))
|
| 118 |
+
}
|
| 119 |
+
#' Initial values for WALD
|
| 120 |
+
#' @description This function generates initial values for the parameters.
|
| 121 |
+
#' @param y vector with the response variable.
|
| 122 |
+
#' @return returns a vector with starting values.
|
| 123 |
+
#' @keywords internal
|
| 124 |
+
#' @export
|
| 125 |
+
#' @importFrom stats var
|
| 126 |
+
wald_start <- function(y) {
|
| 127 |
+
mu <- sqrt(mean(y)/var(y))
|
| 128 |
+
sigma <- mu*mean(y)
|
| 129 |
+
return(c(mu, sigma))
|
| 130 |
+
}
|
| 131 |
+
|
dExWALD.R
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#' The Ex-Wald distribution
|
| 2 |
+
#'
|
| 3 |
+
#' @author Freddy Hernandez, \email{fhernanb@unal.edu.co}
|
| 4 |
+
#'
|
| 5 |
+
#' @description
|
| 6 |
+
#' These functions define the density, distribution function, quantile
|
| 7 |
+
#' function and random generation for the Ex-Wald distribution
|
| 8 |
+
#' with parameter \eqn{\mu}, \eqn{\sigma} and \eqn{\nu}.
|
| 9 |
+
#'
|
| 10 |
+
#' @param x,q vector of (non-negative integer) quantiles.
|
| 11 |
+
#' @param p vector of probabilities.
|
| 12 |
+
#' @param mu vector of the mu parameter.
|
| 13 |
+
#' @param sigma vector of the sigma parameter.
|
| 14 |
+
#' @param nu vector of the nu parameter.
|
| 15 |
+
#' @param n number of random values to return.
|
| 16 |
+
#' @param log,log.p logical; if TRUE, probabilities p are given as log(p).
|
| 17 |
+
#' @param lower.tail logical; if TRUE (default), probabilities are
|
| 18 |
+
#' P[X <= x], otherwise, P[X > x].
|
| 19 |
+
#'
|
| 20 |
+
#' @seealso \link{ExWALD}
|
| 21 |
+
#'
|
| 22 |
+
#' @references
|
| 23 |
+
#' Schwarz, W. (2001). The ex-Wald distribution as a descriptive model
|
| 24 |
+
#' of response times. Behavior Research Methods,
|
| 25 |
+
#' Instruments, & Computers, 33, 457-469.
|
| 26 |
+
#'
|
| 27 |
+
#' Heathcote, A. (2004). Fitting Wald and ex-Wald distributions to
|
| 28 |
+
#' response time data: An example using functions for the S-PLUS package.
|
| 29 |
+
#' Behavior Research Methods, Instruments, & Computers, 36, 678-694.
|
| 30 |
+
#'
|
| 31 |
+
#' @details
|
| 32 |
+
#' The Wald distribution with parameters \eqn{\mu}, \eqn{\sigma}
|
| 33 |
+
#' and \eqn{\nu} has density given by
|
| 34 |
+
#'
|
| 35 |
+
#' \eqn{f(x |\mu, \sigma, \nu) = \frac{1}{\nu} \exp(\frac{-x}{\nu} + \sigma(\mu-k)) F_W(x|k, \sigma) \, \text{for} \, k \geq 0}
|
| 36 |
+
#'
|
| 37 |
+
#' \eqn{f(x |\mu, \sigma, \nu) = \frac{1}{\nu} \exp\left( \frac{-(\sigma-\mu)^2}{2x} \right) Re \left( w(k^\prime \sqrt{x/2} + \frac{\sigma i}{\sqrt{2x}}) \right) \, \text{for} \, k < 0}
|
| 38 |
+
#'
|
| 39 |
+
#' where \eqn{k=\sqrt{\mu^2-\frac{2}{\nu}}},
|
| 40 |
+
#' \eqn{k^\prime=\sqrt{\frac{2}{\nu}-\mu^2}} and
|
| 41 |
+
#' \eqn{F_W} corresponds to the cumulative function of
|
| 42 |
+
#' the Wald distribution.
|
| 43 |
+
#'
|
| 44 |
+
#' More details about those expressions
|
| 45 |
+
#' can be found on page 680 from Heathcote (2004).
|
| 46 |
+
#'
|
| 47 |
+
#' @return
|
| 48 |
+
#' \code{dExWALD} gives the density, \code{pExWALD} gives the distribution
|
| 49 |
+
#' function, \code{qExWALD} gives the quantile function, \code{rExWALD}
|
| 50 |
+
#' generates random deviates.
|
| 51 |
+
#'
|
| 52 |
+
#' @example examples/examples_dExWALD.R
|
| 53 |
+
#'
|
| 54 |
+
#' @export
|
| 55 |
+
dExWALD <- function(x, mu=1.5, sigma=1.5, nu=2, log=FALSE) {
|
| 56 |
+
if (any(mu<=0))
|
| 57 |
+
stop ("mu must be positive")
|
| 58 |
+
if (any(sigma<=0))
|
| 59 |
+
stop ("sigma must be positive")
|
| 60 |
+
if (any(nu<=0))
|
| 61 |
+
stop ("nu must be positive")
|
| 62 |
+
|
| 63 |
+
# Freddy's code
|
| 64 |
+
k <- mu^2 - 2/nu
|
| 65 |
+
if (k < 0) {
|
| 66 |
+
part1 <- -log(nu) + mu*sigma - sigma^2/(2*x) - x*mu^2/2
|
| 67 |
+
element1 <- sqrt(-x*k/2)
|
| 68 |
+
element2 <- sigma/sqrt(2*x)
|
| 69 |
+
element3 <- ifelse(element1 < 30 & element2 < 25,
|
| 70 |
+
rew(element1, element2),
|
| 71 |
+
0)
|
| 72 |
+
element3 <- abs(element3)
|
| 73 |
+
part2 <- log(element3)
|
| 74 |
+
res <- part1 + part2
|
| 75 |
+
}
|
| 76 |
+
else {
|
| 77 |
+
k <- sqrt(k)
|
| 78 |
+
part1 <- -log(nu)
|
| 79 |
+
part2 <- sigma*(mu-k)-x/nu
|
| 80 |
+
part3 <- pWALD(x, mu=k, sigma=sigma, log.p=TRUE)
|
| 81 |
+
res <- part1 + part2 + part3 # Expression (3)
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
if (log)
|
| 85 |
+
return(res)
|
| 86 |
+
else
|
| 87 |
+
return(exp(res))
|
| 88 |
+
}
|
| 89 |
+
# Vectorizing
|
| 90 |
+
dExWALD <- Vectorize(dExWALD)
|
| 91 |
+
#' @export
|
| 92 |
+
#' @rdname dExWALD
|
| 93 |
+
pExWALD <- function(q, mu=1.5, sigma=1.5, nu=2,
|
| 94 |
+
lower.tail = TRUE, log.p = FALSE) {
|
| 95 |
+
if (any(mu<=0))
|
| 96 |
+
stop ("mu must be positive")
|
| 97 |
+
if (any(sigma<=0))
|
| 98 |
+
stop ("sigma must be positive")
|
| 99 |
+
if (any(nu<=0))
|
| 100 |
+
stop ("nu must be positive")
|
| 101 |
+
|
| 102 |
+
cdf <- pWALD(q, mu, sigma) - nu * dExWALD(q, mu, sigma, nu)
|
| 103 |
+
if (lower.tail == TRUE) {
|
| 104 |
+
cdf <- cdf
|
| 105 |
+
}
|
| 106 |
+
else {
|
| 107 |
+
cdf <- 1 - cdf
|
| 108 |
+
}
|
| 109 |
+
if (log.p == FALSE){
|
| 110 |
+
cdf <- cdf}
|
| 111 |
+
else {cdf <- log(cdf)}
|
| 112 |
+
return(cdf)
|
| 113 |
+
}
|
| 114 |
+
#' @export
|
| 115 |
+
#' @rdname dExWALD
|
| 116 |
+
#' @importFrom stats uniroot
|
| 117 |
+
qExWALD <- function(p, mu=1.5, sigma=1.5, nu=2) {
|
| 118 |
+
if (any(mu<=0))
|
| 119 |
+
stop ("mu must be positive")
|
| 120 |
+
if (any(sigma<=0))
|
| 121 |
+
stop ("sigma must be positive")
|
| 122 |
+
if (any(nu<=0))
|
| 123 |
+
stop ("nu must be positive")
|
| 124 |
+
|
| 125 |
+
# Begin auxiliar function
|
| 126 |
+
my_aux <- function(x, p, mu, sigma, nu)
|
| 127 |
+
pExWALD(x, mu, sigma, nu) - p
|
| 128 |
+
# End auxiliar function
|
| 129 |
+
|
| 130 |
+
uniroot(my_aux, c(0.001, 10000), tol=0.0001,
|
| 131 |
+
mu=mu, sigma=sigma, nu=nu, p=p)$root
|
| 132 |
+
}
|
| 133 |
+
# Vectorizing
|
| 134 |
+
qExWALD <- Vectorize(qExWALD)
|
| 135 |
+
#' @export
|
| 136 |
+
#' @rdname dExWALD
|
| 137 |
+
#' @importFrom stats rexp
|
| 138 |
+
rExWALD <- function(n, mu=1.5, sigma=1.5, nu=2) {
|
| 139 |
+
if (any(mu<=0))
|
| 140 |
+
stop ("mu must be positive")
|
| 141 |
+
if (any(sigma<=0))
|
| 142 |
+
stop ("sigma must be positive")
|
| 143 |
+
if (any(nu<=0))
|
| 144 |
+
stop ("nu must be positive")
|
| 145 |
+
|
| 146 |
+
rWALD(n, mu, sigma) + rexp(n, 1/nu)
|
| 147 |
+
}
|
| 148 |
+
#' Auxiliar function for the Ex-Wald distribution
|
| 149 |
+
#' @description This function is an auxiliar function.
|
| 150 |
+
#' @param x a value for x.
|
| 151 |
+
#' @param y a value for y.
|
| 152 |
+
#' @param block a value.
|
| 153 |
+
#' @param tol is the tolerance.
|
| 154 |
+
#' @param maxseries maximum value for series.
|
| 155 |
+
#' @return returns a vector with starting values.
|
| 156 |
+
#' @keywords internal
|
| 157 |
+
#' @export
|
| 158 |
+
uandv <- function(x, y, firstblock=20, block=0,
|
| 159 |
+
tol=.Machine$double.eps^(2/3), maxseries=20) {
|
| 160 |
+
twoxy <- 2*x*y; xsq <- x^2; iexpxsqpi <- 1/(pi*exp(xsq))
|
| 161 |
+
sin2xy <- sin(twoxy); cos2xy <- cos(twoxy)
|
| 162 |
+
nmat <- matrix(rep((1:firstblock), each = length(x)), nrow = length(x))
|
| 163 |
+
nsqmat <- nmat^2; ny <- nmat*y; twoxcoshny <- 2*x*cosh(ny)
|
| 164 |
+
nsinhny <- nmat*sinh(ny); nsqfrac <- (exp(-nsqmat/4)/(nsqmat+4*xsq))
|
| 165 |
+
u <- (2*pnorm(x*sqrt(2))-1)+iexpxsqpi*(((1-cos2xy)/(2*x))+2*
|
| 166 |
+
((nsqfrac*(2*x-twoxcoshny*cos2xy+nsinhny*sin2xy))%*%rep(1, firstblock)))
|
| 167 |
+
v <- iexpxsqpi*((sin2xy/(2*x))+2*((nsqfrac*(twoxcoshny*sin2xy+
|
| 168 |
+
nsinhny*cos2xy))%*%rep(1,firstblock)))
|
| 169 |
+
n <- firstblock; converged <- rep(F, length(x))
|
| 170 |
+
repeat {
|
| 171 |
+
if ((block<1)||(n>=maxseries)) break
|
| 172 |
+
else {
|
| 173 |
+
if ((n+block)>maxseries) block <- (maxseries-n)
|
| 174 |
+
nmat <- matrix(rep((n+1):(n+block), each=sum(!converged)),
|
| 175 |
+
nrow=sum(!converged))
|
| 176 |
+
nsq <- nmat^2; ny <- nmat*y[!converged];
|
| 177 |
+
twoxcoshny <- 2*x[!converged]*cosh(ny); nsinhny <- nmat*sinh(ny)
|
| 178 |
+
nsqfrac <- (exp(-nsq/4)/(nsq+4*xsq[!converged]))
|
| 179 |
+
du <- iexpxsqpi[!converged]*((2*nsqfrac*(2*x[!converged]-
|
| 180 |
+
twoxcoshny*cos2xy[!converged]+nsinhny*sin2xy[!converged]))
|
| 181 |
+
%*%rep(1,block))
|
| 182 |
+
dv <- iexpxsqpi[!converged]*((2*nsqfrac*(twoxcoshny*sin2xy[!converged]+
|
| 183 |
+
nsinhny*cos2xy[!converged]))%*%rep(1, block))
|
| 184 |
+
u[!converged] <- u[!converged]+du;
|
| 185 |
+
v[!converged] <- v[!converged]+dv
|
| 186 |
+
converged[!converged] <- ((du<tol)&(dv<tol))
|
| 187 |
+
if (all(converged)) break
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
cbind(u,v)
|
| 191 |
+
}
|
| 192 |
+
|
dWALD.R
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#' The Wald distribution
|
| 2 |
+
#'
|
| 3 |
+
#' @author Sofia Cuartas, \email{scuartasg@unal.edu.co}
|
| 4 |
+
#'
|
| 5 |
+
#' @description
|
| 6 |
+
#' These functions define the density, distribution function, quantile
|
| 7 |
+
#' function and random generation for the Wald distribution
|
| 8 |
+
#' with parameter \eqn{\mu} and \eqn{\sigma}.
|
| 9 |
+
#'
|
| 10 |
+
#' @param x,q vector of (non-negative integer) quantiles.
|
| 11 |
+
#' @param p vector of probabilities.
|
| 12 |
+
#' @param mu vector of the mu parameter.
|
| 13 |
+
#' @param sigma vector of the sigma parameter.
|
| 14 |
+
#' @param n number of random values to return.
|
| 15 |
+
#' @param log,log.p logical; if TRUE, probabilities p are given as log(p).
|
| 16 |
+
#' @param lower.tail logical; if TRUE (default), probabilities are
|
| 17 |
+
#' P[X <= x], otherwise, P[X > x].
|
| 18 |
+
#'
|
| 19 |
+
#' @seealso \link{WALD}
|
| 20 |
+
#'
|
| 21 |
+
#' @references
|
| 22 |
+
#' Heathcote, A. (2004). Fitting Wald and ex-Wald distributions to
|
| 23 |
+
#' response time data: An example using functions for the S-PLUS package.
|
| 24 |
+
#' Behavior Research Methods, Instruments, & Computers, 36, 678-694.
|
| 25 |
+
#'
|
| 26 |
+
#' @seealso \link{WALD}.
|
| 27 |
+
#'
|
| 28 |
+
#' @details
|
| 29 |
+
#' The Wald distribution with parameters \eqn{\mu} and \eqn{\sigma} has density given by
|
| 30 |
+
#'
|
| 31 |
+
#' \eqn{f(x |\mu, \sigma)=\frac{\sigma}{\sqrt{2 \pi x^3}} \exp \left[-\frac{(\sigma-\mu x)^2}{2x}\right ],}
|
| 32 |
+
#'
|
| 33 |
+
#' for \eqn{x < 0}.
|
| 34 |
+
#'
|
| 35 |
+
#' @return
|
| 36 |
+
#' \code{dWALD} gives the density, \code{pWALD} gives the distribution
|
| 37 |
+
#' function, \code{qWALD} gives the quantile function, \code{rWALD}
|
| 38 |
+
#' generates random deviates.
|
| 39 |
+
#'
|
| 40 |
+
#' @example examples/examples_dWALD.R
|
| 41 |
+
#'
|
| 42 |
+
#' @export
|
| 43 |
+
dWALD <- function(x, mu, sigma, log=FALSE) {
|
| 44 |
+
if (any(x <= -1e-15)) stop(paste("x must be positive", "\n", ""))
|
| 45 |
+
if (any(mu <= 0)) stop(paste("mu must be positive 0", "\n", ""))
|
| 46 |
+
if (any(sigma <= 0)) stop(paste("sigma must be positive", "\n", ""))
|
| 47 |
+
|
| 48 |
+
res <- log(sigma) - 0.5*log(2*pi) - 1.5*log(x) - (sigma-mu*x)^2/(2*x)
|
| 49 |
+
|
| 50 |
+
if(log == FALSE)
|
| 51 |
+
return(exp(res))
|
| 52 |
+
else
|
| 53 |
+
return(res)
|
| 54 |
+
}
|
| 55 |
+
#' @export
|
| 56 |
+
#' @rdname dWALD
|
| 57 |
+
#' @importFrom stats pnorm
|
| 58 |
+
pWALD <- function(q, mu , sigma, lower.tail = TRUE, log.p = FALSE){
|
| 59 |
+
if (any(q <= -1e-15)) stop(paste("q must be positive", "\n", ""))
|
| 60 |
+
if (any(mu <= 0)) stop(paste("mu must be positive", "\n", ""))
|
| 61 |
+
if (any(sigma <= 0)) stop(paste("sigma must be positive", "\n", ""))
|
| 62 |
+
sqrtq <- sqrt(q)
|
| 63 |
+
k1 <- (mu*q-sigma)/sqrtq
|
| 64 |
+
k2 <- (mu*q+sigma)/sqrtq
|
| 65 |
+
p1 <- exp(2*sigma*mu)
|
| 66 |
+
p2 <- pnorm(-k2)
|
| 67 |
+
bad <- (p1==Inf) | (p2==0)
|
| 68 |
+
p <- p1*p2
|
| 69 |
+
p[bad] <- (exp(-(k1[bad]^2)/2 - 0.94/(k2[bad]^2))/(k2[bad]*((2*pi)^.5)))
|
| 70 |
+
cdf <- p + pnorm(k1)
|
| 71 |
+
if (lower.tail == TRUE) {
|
| 72 |
+
cdf <- cdf
|
| 73 |
+
}
|
| 74 |
+
else {
|
| 75 |
+
cdf <- 1 - cdf
|
| 76 |
+
}
|
| 77 |
+
if (log.p == FALSE){
|
| 78 |
+
cdf <- cdf}
|
| 79 |
+
else {cdf <- log(cdf)}
|
| 80 |
+
return(cdf)
|
| 81 |
+
}
|
| 82 |
+
#' @export
|
| 83 |
+
#' @rdname dWALD
|
| 84 |
+
qWALD <- function(p, mu, sigma, lower.tail=TRUE, log.p=FALSE){
|
| 85 |
+
if (any(mu <= 0)) stop(paste("mu must be positive 0", "\n", ""))
|
| 86 |
+
if (any(sigma <= 0)) stop(paste("sigma must be positive", "\n", ""))
|
| 87 |
+
|
| 88 |
+
if (log.p == TRUE) p <- exp(p)
|
| 89 |
+
else p <- p
|
| 90 |
+
if (lower.tail == TRUE) p <- p
|
| 91 |
+
else p <- 1 - p
|
| 92 |
+
|
| 93 |
+
if (any(p < 0) | any(p > 1)) stop(paste("p must be between 0 and 1", "\n", ""))
|
| 94 |
+
|
| 95 |
+
F.inv <- function(y, mu, sigma, nu) {
|
| 96 |
+
uniroot(function(x) {pWALD(x,mu,sigma) - y},
|
| 97 |
+
interval=c(0, 99999))$root
|
| 98 |
+
}
|
| 99 |
+
F.inv <- Vectorize(F.inv)
|
| 100 |
+
F.inv(p, mu, sigma)
|
| 101 |
+
}
|
| 102 |
+
#' @export
|
| 103 |
+
#' @rdname dWALD
|
| 104 |
+
#' @importFrom stats rchisq
|
| 105 |
+
rWALD <- function(n, mu, sigma){
|
| 106 |
+
if (any(n <= 0)) stop(paste("n must be positive","\n",""))
|
| 107 |
+
if (any(mu <= 0)) stop(paste("mu must be positive 0", "\n", ""))
|
| 108 |
+
if (any(sigma <= 0)) stop(paste("sigma must be positive", "\n", ""))
|
| 109 |
+
y2 <- rchisq(n, 1)
|
| 110 |
+
y2onm <- y2/mu
|
| 111 |
+
u <- runif(n)
|
| 112 |
+
r1 <- (2*sigma + y2onm - sqrt(y2onm*(4*sigma+y2onm)))/(2*mu)
|
| 113 |
+
r2 <- (sigma/mu)^2/r1
|
| 114 |
+
r <- ifelse(u < sigma/(sigma+mu*r1), r1, r2)
|
| 115 |
+
r
|
| 116 |
+
}
|
server.R
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
source("dWALD.R")
|
| 2 |
+
source("WALD.R")
|
| 3 |
+
source("dExWALD.R")
|
| 4 |
+
source("ExWALD.R")
|
| 5 |
+
|
| 6 |
+
library(shiny)
|
| 7 |
+
library(MASS)
|
| 8 |
+
library(gamlss)
|
| 9 |
+
|
| 10 |
+
shinyServer(function(input, output) {
|
| 11 |
+
|
| 12 |
+
datos_reactivo <- reactive({
|
| 13 |
+
req(input$datos)
|
| 14 |
+
|
| 15 |
+
datos_char <- unlist(strsplit(input$datos, ","))
|
| 16 |
+
datos_num <- as.numeric(trimws(datos_char))
|
| 17 |
+
datos_num <- datos_num[!is.na(datos_num)]
|
| 18 |
+
|
| 19 |
+
if(length(datos_num) == 0) {
|
| 20 |
+
return(NULL)
|
| 21 |
+
} else {
|
| 22 |
+
return(datos_num)
|
| 23 |
+
}
|
| 24 |
+
})
|
| 25 |
+
|
| 26 |
+
output$histograma <- renderPlot({
|
| 27 |
+
datos <- datos_reactivo()
|
| 28 |
+
req(datos)
|
| 29 |
+
|
| 30 |
+
dist_sel <- input$dist
|
| 31 |
+
|
| 32 |
+
#par(mfrow=c(2, 1))
|
| 33 |
+
|
| 34 |
+
hist(datos, probability = TRUE, col = "lightblue",
|
| 35 |
+
main = paste("Histogram and estimated density for", dist_sel),
|
| 36 |
+
xlab = "x")
|
| 37 |
+
|
| 38 |
+
x_seq <- seq(min(datos), max(datos), length.out = 200)
|
| 39 |
+
|
| 40 |
+
# Estimation y curva seg煤n distribuci贸n elegida
|
| 41 |
+
if(dist_sel == "Normal") {
|
| 42 |
+
|
| 43 |
+
fit <- gamlss(datos~1, family=NO)
|
| 44 |
+
mu <- coef(fit, what="mu")
|
| 45 |
+
sigma <- exp(coef(fit, what="sigma"))
|
| 46 |
+
y <- dNO(x_seq, mu = mu, sigma = sigma)
|
| 47 |
+
lines(x_seq, y, col = "tomato", lwd=3)
|
| 48 |
+
legend("topright", bty="n",
|
| 49 |
+
legend="Estimated density",
|
| 50 |
+
lwd=3, col="tomato")
|
| 51 |
+
|
| 52 |
+
} else if(dist_sel == "WALD") {
|
| 53 |
+
# Ajuste con fitdistr
|
| 54 |
+
fit <- tryCatch({
|
| 55 |
+
mod <- gamlss(datos~1, family=WALD)
|
| 56 |
+
}, error = function(e) NULL)
|
| 57 |
+
|
| 58 |
+
if(!is.null(fit)) {
|
| 59 |
+
mu <- exp(coef(fit, what="mu"))
|
| 60 |
+
sigma <- exp(coef(fit, what="sigma"))
|
| 61 |
+
y <- dWALD(x_seq, mu=mu, sigma=sigma)
|
| 62 |
+
lines(x_seq, y, col = "tomato", lwd=3)
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
} else if(dist_sel == "ExWALD") {
|
| 66 |
+
fit <- tryCatch({
|
| 67 |
+
fit <- gamlss(datos~1, family=ExWALD)
|
| 68 |
+
}, error = function(e) NULL)
|
| 69 |
+
|
| 70 |
+
if(!is.null(fit)) {
|
| 71 |
+
mu <- exp(coef(fit, what="mu"))
|
| 72 |
+
sigma <- exp(coef(fit, what="sigma"))
|
| 73 |
+
nu <- exp(coef(fit, what="nu"))
|
| 74 |
+
y <- dExWALD(x_seq, mu=mu, sigma=sigma, nu=nu)
|
| 75 |
+
lines(x_seq, y, col = "tomato", lwd=3)
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
# To plot the residual analysis
|
| 79 |
+
#plot(fit)
|
| 80 |
+
})
|
| 81 |
+
|
| 82 |
+
output$parametros <- renderTable({
|
| 83 |
+
datos <- datos_reactivo()
|
| 84 |
+
req(datos)
|
| 85 |
+
|
| 86 |
+
dist_sel <- input$dist
|
| 87 |
+
|
| 88 |
+
if(dist_sel == "Normal") {
|
| 89 |
+
mu <- mean(datos)
|
| 90 |
+
sigma <- sd(datos)
|
| 91 |
+
data.frame(
|
| 92 |
+
Parameter = c("渭", "蟽", "Mean", "Standard deviation"),
|
| 93 |
+
Estimation = c(mu, sigma, mean(datos), sd(datos))
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
} else if(dist_sel == "WALD") {
|
| 97 |
+
fit <- tryCatch({
|
| 98 |
+
mod <- gamlss(datos~1, family=WALD)
|
| 99 |
+
}, error = function(e) NULL)
|
| 100 |
+
|
| 101 |
+
if(!is.null(fit)) {
|
| 102 |
+
mu <- exp(coef(fit, what="mu"))
|
| 103 |
+
sigma <- exp(coef(fit, what="sigma"))
|
| 104 |
+
data.frame(
|
| 105 |
+
Parameter = c("渭", "蟽", "Mean", "Standard deviation"),
|
| 106 |
+
Estimation = c(mu, sigma, mean(datos), sd(datos))
|
| 107 |
+
)
|
| 108 |
+
} else {
|
| 109 |
+
data.frame(
|
| 110 |
+
Parameter = "Error",
|
| 111 |
+
Estimation = "We cannot fit WALD"
|
| 112 |
+
)
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
} else if(dist_sel == "ExWALD") {
|
| 116 |
+
fit <- tryCatch({
|
| 117 |
+
fit <- gamlss(datos~1, family=ExWALD)
|
| 118 |
+
}, error = function(e) NULL)
|
| 119 |
+
|
| 120 |
+
if(!is.null(fit)) {
|
| 121 |
+
mu <- exp(coef(fit, what="mu"))
|
| 122 |
+
sigma <- exp(coef(fit, what="sigma"))
|
| 123 |
+
nu <- exp(coef(fit, what="nu"))
|
| 124 |
+
data.frame(
|
| 125 |
+
Parameter = c("渭", "蟽", "谓", "Mean", "Standard deviation"),
|
| 126 |
+
Estimation = c(mu, sigma, nu, mean(datos), sd(datos))
|
| 127 |
+
)
|
| 128 |
+
} else {
|
| 129 |
+
data.frame(
|
| 130 |
+
Parameter = "Error",
|
| 131 |
+
Estimation = "We cannot fit ExWALD"
|
| 132 |
+
)
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
})
|
| 136 |
+
|
| 137 |
+
})
|
ui.R
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
library(shiny)
|
| 2 |
+
|
| 3 |
+
shinyUI(fluidPage(
|
| 4 |
+
titlePanel("Shiny app to estimate parameters for Reaction Times (RTs)"),
|
| 5 |
+
|
| 6 |
+
sidebarLayout(
|
| 7 |
+
sidebarPanel(
|
| 8 |
+
textInput("datos", "Enter numbers separated by commas:",
|
| 9 |
+
placeholder = "Example: 1.2, 3.4, 2.1, 5.6, 4.3"),
|
| 10 |
+
|
| 11 |
+
selectInput("dist", "Select the distribution:",
|
| 12 |
+
choices = c("Normal", "WALD", "ExWALD"),
|
| 13 |
+
selected = "Normal"),
|
| 14 |
+
br(),
|
| 15 |
+
p("Example 1"),
|
| 16 |
+
p("The next random sample was obtained from a N(15, 3),"),
|
| 17 |
+
p("copy and paste the next numbers:"),
|
| 18 |
+
p("16.5, 19.8, 11.8, 14.6, 14.2, 5.8, 12.8, 17.5, 22.9, 7.5, 9.4,
|
| 19 |
+
14.8, 15.3, 12.9, 12.6, 13.4, 20.2, 16.4, 18.4, 15, 15.1, 18.1,
|
| 20 |
+
15.9, 16.5, 15.1, 15, 17, 16.5, 19.9, 11.9, 14.1, 13.1, 12, 15.8,
|
| 21 |
+
16.3, 16.1, 13.3, 11.2, 17.8, 17.9, 11.4, 15.6, 10.7, 15.1, 13.3,
|
| 22 |
+
16.6, 15.5, 12.2, 14.6, 15.2"),
|
| 23 |
+
br(),
|
| 24 |
+
p("Example 3"),
|
| 25 |
+
p("The next random sample was obtained from a ExWALD(2, 5, 1.2),"),
|
| 26 |
+
p("copy and paste the next numbers:"),
|
| 27 |
+
p("2.3, 3.8, 3.1, 3.9, 3.2, 3.8, 2.8, 1.3, 4.2, 2.3, 2.9, 2.6,
|
| 28 |
+
3.8, 5, 4.6, 3.5, 9.6, 2.3, 3.9, 3.1, 8.6, 2.2, 5.6, 2.7, 2,
|
| 29 |
+
3.5, 5.4, 5.1, 3, 2, 5.1, 4.6, 3.7, 3.6, 2.3, 2.3, 3.6, 1.6,
|
| 30 |
+
3.6, 2.9, 3.1, 5.4, 3.2, 2.4, 3.4, 3.7, 4.4, 6.3, 2.9, 3.2")
|
| 31 |
+
),
|
| 32 |
+
|
| 33 |
+
mainPanel(
|
| 34 |
+
plotOutput("histograma"),
|
| 35 |
+
tableOutput("parametros")
|
| 36 |
+
)
|
| 37 |
+
)
|
| 38 |
+
))
|