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órychglmfunkcje 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)")

?

questionAnswers(2)

yourAnswerToTheQuestion