zmodyfikuj funkcję glm, aby zaadoptować określoną przez użytkownika funkcję łącza w R
Wglm
w R domyślne funkcje łącza dlaGamma
rodzina jestinverse
,identity
ilog
. Jeśli chodzi o moje konkretne pytanie, muszę użyć regresji gamma z odpowiedziąY
i zmodyfikowana funkcja łącza w postacilog(E(Y)-1))
. Dlatego rozważam modyfikację niektórychglm
funkcje związane z R. Istnieje kilka funkcji, które mogą być istotne i szukam pomocy dla każdego, kto miał wcześniej doświadczenie w tym zakresie.
Na przykład funkcjeGamma
jest zdefiniowany jako
function (link = "inverse")
{
linktemp <- substitute(link)
if (!is.character(linktemp))
linktemp <- deparse(linktemp)
okLinks <- c("inverse", "log", "identity")
if (linktemp %in% okLinks)
stats <- make.link(linktemp)
else if (is.character(link))
stats <- make.link(link)
else {
if (inherits(link, "link-glm")) {
stats <- link
if (!is.null(stats$name))
linktemp <- stats$name
}
else {
stop(gettextf("link \"%s\" not available for gamma family; available links are %s",
linktemp, paste(sQuote(okLinks), collapse = ", ")),
domain = NA)
}
}
variance <- function(mu) mu^2
validmu <- function(mu) all(mu > 0)
dev.resids <- function(y, mu, wt) -2 * wt * (log(ifelse(y ==
0, 1, y/mu)) - (y - mu)/mu)
aic <- function(y, n, mu, wt, dev) {
n <- sum(wt)
disp <- dev/n
-2 * sum(dgamma(y, 1/disp, scale = mu * disp, log = TRUE) *
wt) + 2
}
initialize <- expression({
if (any(y <= 0)) stop("non-positive values not allowed for the 'gamma' family")
n <- rep.int(1, nobs)
mustart <- y
})
simfun <- function(object, nsim) {
wts <- object$prior.weights
if (any(wts != 1))
message("using weights as shape parameters")
ftd <- fitted(object)
shape <- MASS::gamma.shape(object)$alpha * wts
rgamma(nsim * length(ftd), shape = shape, rate = shape/ftd)
}
structure(list(family = "Gamma", link = linktemp, linkfun = stats$linkfun,
linkinv = stats$linkinv, variance = variance, dev.resids = dev.resids,
aic = aic, mu.eta = stats$mu.eta, initialize = initialize,
validmu = validmu, valideta = stats$valideta, simulate = simfun),
class = "family")
}
Ponadto, aby użyć poleceniaglm(y ~ log(mu), family = Gamma(link = MyLink))
, czy muszę także zmodyfikowaćglm.fit
funkcjonować? Dziękuję Ci!
Aktualizacje i nowe pytanie
Zgodnie z komentarzami @Ben Bolkera musimy napisać nową funkcję linku o nazwievlog
(z prawdziwym imieniem"log(exp(y)-1)"
). Uważam, żemake.link
funkcja może być odpowiedzialna za taką modyfikację. Jest zdefiniowany jako
function (link)
{
switch(link, logit = {
linkfun <- function(mu) .Call(C_logit_link, mu)
linkinv <- function(eta) .Call(C_logit_linkinv, eta)
mu.eta <- function(eta) .Call(C_logit_mu_eta, eta)
valideta <- function(eta) TRUE
},
...
}, log = {
linkfun <- function(mu) log(mu)
linkinv <- function(eta) pmax(exp(eta), .Machine$double.eps)
mu.eta <- function(eta) pmax(exp(eta), .Machine$double.eps)
valideta <- function(eta) TRUE
},
...
structure(list(linkfun = linkfun, linkinv = linkinv, mu.eta = mu.eta,
valideta = valideta, name = link), class = "link-glm")
}
Moje pytanie brzmi: jeśli chcemyna stałe dodaj tę funkcję łączavlog
doglm
, więc w każdej sesji R możemy użyćglm(y~x,family=Gamma(link="log(exp(y)-1)"))
bezpośrednio użyjemyfix(make.link)
a następnie dodaj definicjęvlog
do jego ciała? Lubfix()
może to zrobić tylko w bieżącej sesji R? Dzięki jeszcze raz!
Jeszcze jedna rzecz: Zdaję sobie sprawę, że może trzeba zmodyfikować inną funkcję. To jestGamma
, zdefiniowana jako
function (link = "inverse")
{
linktemp <- substitute(link)
if (!is.character(linktemp))
linktemp <- deparse(linktemp)
okLinks <- c("inverse", "log", "identity")
if (linktemp %in% okLinks)
stats <- make.link(linktemp)
else if (is.character(link))
stats <- make.link(link)
else {
if (inherits(link, "link-glm")) {
stats <- link
if (!is.null(stats$name))
linktemp <- stats$name
}
else {
stop(gettextf("link \"%s\" not available for gamma family; available links are %s",
linktemp, paste(sQuote(okLinks), collapse = ", ")),
domain = NA)
}
}
variance <- function(mu) mu^2
validmu <- function(mu) all(mu > 0)
dev.resids <- function(y, mu, wt) -2 * wt * (log(ifelse(y ==
0, 1, y/mu)) - (y - mu)/mu)
aic <- function(y, n, mu, wt, dev) {
n <- sum(wt)
disp <- dev/n
-2 * sum(dgamma(y, 1/disp, scale = mu * disp, log = TRUE) *
wt) + 2
}
initialize <- expression({
if (any(y <= 0)) stop("non-positive values not allowed for the 'gamma' family")
n <- rep.int(1, nobs)
mustart <- y
})
simfun <- function(object, nsim) {
wts <- object$prior.weights
if (any(wts != 1))
message("using weights as shape parameters")
ftd <- fitted(object)
shape <- MASS::gamma.shape(object)$alpha * wts
rgamma(nsim * length(ftd), shape = shape, rate = shape/ftd)
}
structure(list(family = "Gamma", link = linktemp, linkfun = stats$linkfun,
linkinv = stats$linkinv, variance = variance, dev.resids = dev.resids,
aic = aic, mu.eta = stats$mu.eta, initialize = initialize,
validmu = validmu, valideta = stats$valideta, simulate = simfun),
class = "family")
}
Myślę, że musimy również dokonać przeglądu
okLinks <- c("inverse", "log", "identity")
do
okLinks <- c("inverse", "log", "identity", "log(exp(y)-1)")
?