John
John

Reputation: 1947

Manually created formula seems to not work...but why?

Let's consider data following :

library(pglm)
data('UnionWage', package = 'pglm')
df1 <- data.frame(UnionWage[1:2],'wage' = UnionWage$wage, 'exper' = UnionWage$exper)
head(df1)
  id year     wage exper
1 13 1980 1.197540     1
2 13 1981 1.853060     2
3 13 1982 1.344462     3
4 13 1983 1.433213     4
5 13 1984 1.568125     5
6 13 1985 1.699891     6 

I want to write a function which will fit logistic random panel regression to data :

Function

fit_panel_binary <- function(y, x) {
   x <- cbind(x, y)
  #Taking varnames since 3 (first and second are respectively id and year)
  varnames <- names(x)[3:(length(x))]

  #Excluding dependent variable from varnames
  varnames <- varnames[!(varnames == names(y))]

  #Creating formula of independent variables (sum)
  form <- paste0(varnames, collapse = "+")
  x_copy <- data.frame(x)

  #Performing panel random regression
  model <- pglm(as.formula(paste0(names(y), "~", form)), data = as.matrix(x_copy), 
  model = 'random', family = binomial(link = 'logit'))
}

And error occrus :

fit_panel_binary(UnionWage['union'],df1)
Error in if (!id.name %in% names(x)) stop(paste("variable ", id.name,  : 
  argument is of length zero 

I though that I put formula incorrectly so I changed my function to outputs formula paste0(names(y), "~", form) and this is what I got :

"union~wage+exper"

It seems that formula is correct, but regression says something different. DO you know where is the problem ?

Upvotes: 0

Views: 64

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173858

Unfortunately, because of the way pglm captures its arguments using non-standard evaluation, it doesn't like being passed formulas that have to be evaluated (i.e. formulas that aren't typed in situ). You can get round this by calling it with do.call, but even then you have to be careful that the data is available in the frame in which pglm is called. So you have to do something like:

fit_panel_binary <- function(y, x) {

  x <- cbind(x, y)
  varnames <- names(x)[3:(length(x))]
  varnames <- varnames[!(varnames == names(y))]
  form     <- paste0(varnames, collapse = "+")
  x_copy   <- data.frame(x)
  form     <- as.formula(paste(names(y), "~", form))
  params   <- list(formula = form, data = x_copy, model = "random",
                   family  = binomial(link = "logit"))
  pglm_env <- list2env(params, envir = new.env())
  
  do.call("pglm", params, envir = pglm_env)
}

Allowing:

fit_panel_binary(UnionWage['union'], df1)
#> Maximum Likelihood estimation
#> Newton-Raphson maximisation, 6 iterations
#> Return code 1: gradient close to zero
#> Log-Likelihood: -1655.081 (4 free parameter(s))
#> Estimate(s): -3.428254 0.8305558 -0.06590541 4.2625

Created on 2020-12-08 by the reprex package (v0.3.0)

Upvotes: 2

Related Questions