0
votes

What I am trying to do should be fairly easy: I estimate a tobit model using the R package Zelig. From this I want to create a tex output using texreg. But what I get back is the error message:

Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘extract’ for signature ‘"Zelig-tobit"’

This is rather strange as texreg does have an extraction method for tobit models. I also tried specifying a function myself but could not get it to work. Here is an example code:

library(Zelig)
library(texreg)

a <- c(2, 2, 2, 4, 3, 5, 9, 9, 9)
b <- c(18, 20, 19, 17, 22, 48, 12, 22, 37)
c <- c(0.1, 0.02, 0.5, 1.2, 0.9, 0.1, 1.1, 0.7, 0.6)

dat <- data.frame(a, b, c)

model <- zelig(a ~ b + c, below = 2, above = 9, model = "tobit", data = dat)

texreg(model)

I am using R Studio on a Windows computer, the texreg version is 1.36.4 and the Zelig version 5.0-11.

This question seemed closely related to my problem: texreg-ing Tobit output from zelig package (R)

However, according to this it should have been fixed a few versions ago, which is not the case for me.

Thanks in advance for your help!

(Btw, I also tried using stargazer instead of texreg which yielded me just another error message.)


I tried to write my own extract function but due to my amateurishness in function writing can't get it to work. Here is what I did:

extract.tob <- function(model, include.iterations = TRUE, include.loglik = TRUE,
                        include.wald = TRUE, ...) {

  s <- model
  names <- rownames(s$coef)
  co <- s$coef[, 1]
  se <- s$coef[, 2]
  pval <- s$coef[, 4]

  gof <- numeric()
  gof.names <- character()
  gof.decimal <- logical()

  if (include.iterations == TRUE) {
    it <- s$iterations
    gof <- c(gof, it)
    gof.names <- c(gof.names, "Number of\\iterations")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.loglik == TRUE) {
    ll <- s$logLik
    gof <- c(gof, ll)
    gof.names <- c(gof.names, "Log-\\likelihood")
    gof.decimal <- c(gof.decimal, TRUE)
  }
  if (include.wald == TRUE) {
    wd <- s$wald
    gof <- c(gof, wd)
    gof.names <- c(gof.names, "Wald-\\statistic")
    gof.decimal <- c(gof.decimal, TRUE)
  }

  tr <- createTexreg(
  coef.names = names,
  coef = co,
  se = se,
  pvalues = pval,
  gof.names = gof.names,
  gof = gof,
  gof.decimal = gof.decimal
  )
  return(tr) 

}  

setMethod("extract", signature = className("Zelig-tobit", "Zelig"),
          definition = extract.tob)

As I see it, the zelig model is already "summarized", that is why I set s <- model instead of summary(model) as in the example. My main problem seems to be that I can't get the needed statistics (log-likelihood, wald ...) out of the model as I do not know how to adress them. The output of str() and so on does not help me with this. Apart from simply not knowing the "names" of the statistics, there also seems to be a problem with how to adress them.

When I try something like "model$coef" I get:

Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
‘coef’ is not a valid field or method name for reference class “Zelig-tobit”

With "model@coef" I get:

Error: no slot of name "coef" for this object of class "Zelig-tobit"

And model[,1] yields me:

Error in modelt6[, 1] : object of type 'S4' is not subsettable

Does anyone have any idea how to make the extract function work? Or another, easier way to get the model output into Latex?

1
Tobit models used to be implemented in Zelig as class zelig with sub-class tobit. This is apparently no longer the case as the model you are creating has class signature Zelig-tobit. You need to write an extension, i.e., an extract method, for texreg. Section 6 of the texreg article in the Journal of Statistical Software (updated version: cran.r-project.org/web/packages/texreg/vignettes/v55i08.pdf) provides some guidance and an example.Philip Leifeld
Thanks for the help! I already tried writing an extract function but can't get to work. See my edited question above. Does anyone have any ideas on this? I am really getting desperate.meatexample
See also this post, where I provide a detailed tutorial on how to write an extract method: stackoverflow.com/questions/38894044/…Philip Leifeld

1 Answers

0
votes

It looks like Zelig-tobit objects as defined in the Zelig package are merely containers that include tobit objects as defined in the AER package, among other things. Therefore you should be able to run texreg on the tobit object that is contained in model:

screenreg(model$zelig.out$z.out[[1]])

yields:

==========================
                Model 1   
--------------------------
(Intercept)     -18.42    
                (16.34)   
b                 0.49    
                 (0.36)   
c                17.51    
                (11.49)   
Log(scale)        1.76 ***
                 (0.49)   
--------------------------
AIC              33.55    
BIC              34.34    
Log Likelihood  -12.78    
Deviance          9.46    
Total             9       
Left-censored     3       
Uncensored        3       
Right-censored    3       
Wald Test         2.35    
==========================
*** p < 0.001, ** p < 0.01, * p < 0.05

It is possible to write an extract method to do that automatically. Here is an example:

# extension for Zelig-tobit objects (Zelig package)
extract.Zeligtobit <- function(model, include.aic = TRUE, include.bic = TRUE, 
    include.loglik = TRUE, include.deviance = TRUE, include.nobs = FALSE, 
    include.censnobs = TRUE, include.wald = TRUE, ...) {
  e <- extract(model$zelig.out$z.out[[1]], include.aic = include.aic, 
      include.bic = include.bic, include.loglik = include.loglik, 
      include.deviance = include.deviance, include.nobs = include.nobs, 
      include.censnobs = include.censnobs, include.wald = include.wald, ...)
  return(e)
}  

setMethod("extract", signature = className("Zelig-tobit", "Zelig"), 
    definition = extract.Zeligtobit)

Now you can just write:

screenreg(model)

which yields the same output as above.

I never quite understood why people use Zelig instead of the original packages like AER. Zelig merely provides wrappers for other existing estimation functions and thereby complicates the data structures in an unnecessary way. E.g., why do you not just use the AER package?