MAHE
MAHE

Reputation: 85

Error using .Call() in R 3.0.+

I am trying to use a function that models nesting success of birds using a logistic exposure link function.

When I run this function using the example code above in R 3.0.0 or 3.0.1, I get the error:

Error in .Call("logit_mu_eta", eta, PACKAGE = "stats") : 
  "logit_mu_eta" not available for .Call() for package "stats"

However, it works fine in R 2.15.3.

I'd like for this to work in more recent versions of R, since I use those for further analysis of the outputs. If anybody has any suggestions, workarounds or corrections, I'd happily try them.

Upvotes: 5

Views: 1997

Answers (2)

Ben Bolker
Ben Bolker

Reputation: 226087

This is not technically a bug, since the function used an internal function whose location has now changed. I have a working example of this posted at https://rpubs.com/bbolker/logregexp ... the key is changing logit_mu_eta to stats:::C_logit_mu_eta as below. Of course, this will still be fragile to future changes in the internals ...

logexp <- function(exposure = 1)
{
    linkfun <- function(mu) qlogis(mu^(1/exposure))
    ## FIXME: is there some trick we can play here to allow
    ##   evaluation in the context of the 'data' argument?
    linkinv <- function(eta)  plogis(eta)^exposure
    mu.eta <- function(eta) exposure * plogis(eta)^(exposure-1) *
      .Call(stats:::C_logit_mu_eta, eta, PACKAGE = "stats")
    valideta <- function(eta) TRUE
    link <- paste("logexp(", deparse(substitute(exposure)), ")",
                   sep="")
    structure(list(linkfun = linkfun, linkinv = linkinv,
                   mu.eta = mu.eta, valideta = valideta, 
                   name = link),
              class = "link-glm")
}

Upvotes: 4

mrip
mrip

Reputation: 15163

That's odd. Might be a bug. You might want to send this to the R mailing list and see what they think. As a crude workaround, you could rewrite that function in R. Here's the C code for it, from the file family.c in src/library/stats/src/:

SEXP logit_mu_eta(SEXP eta)
{
    SEXP ans = PROTECT(duplicate(eta));
    int i, n = LENGTH(eta);
    double *rans = REAL(ans), *reta = REAL(eta);

    if (!n || !isReal(eta))
    error(_("Argument %s must be a nonempty numeric vector"), "eta");
    for (i = 0; i < n; i++) {
    double etai = reta[i];
    double opexp = 1 + exp(etai);

    rans[i] = (etai > THRESH || etai < MTHRESH) ? DOUBLE_EPS :
        exp(etai)/(opexp * opexp);
    }
    UNPROTECT(1);
    return ans;
}

THRESH is defined to be 30. So it looks like you could replace the external call with this function:

logit_mu_eta<-function(x){
  ex<-exp(x)
  ans<-ex/(1+ex)^2
  ans[abs(x)>30]<-.Machine$double.eps
  ans
}

Then you'd have to modify whatever function is calling this.

Upvotes: 0

Related Questions