Избегайте присвоения объекта с именем t
, который совпадает с функцией транспонирования.Глядя на результаты трассировки
makeModel<-function(formula,weights) {
m <- lm(formula, na.action = na.omit, weights = weights)
return(m)
}
run<-function(x) {
f<-formula(x$y~x$x+x$r)
m <- lm(x$y~x$x+x$r, na.action = na.omit, weights = x$size)
m <- lm(f, na.action = na.omit, weights = x$size)
m <- makeModel(f,x$size)
}
l<-20
x<-seq(0,1,1/l)
y<-sqrt(x)
r=round(runif(n=length(x),min=0,max=.8))
n<-1:(l+1)
size=n/sum(n)
x<-data.frame(x,y,r,n,size)
run(x)
#R Error in model.frame.default(formula = formula, weights = weights, na.action = na.omit, :
#R invalid type (closure) for variable '(weights)'
traceback()
#R 7: model.frame.default(formula = formula, weights = weights, na.action = na.omit,
#R drop.unused.levels = TRUE)
#R 6: stats::model.frame(formula = formula, weights = weights, na.action = na.omit,
#R drop.unused.levels = TRUE)
#R 5: eval(mf, parent.frame())
#R 4: eval(mf, parent.frame())
#R 3: lm(formula, na.action = na.omit, weights = weights) at #3
#R 2: makeModel(f, x$size) at #5
#R 1: run(t)
Теперь debug(model.frame.default)
показывает, что эта строка находится там, где идет ошибка из-за этих строк и этой строки .Причина в том, что он вызывает
eval(list(weights = weights), environment(formula), environment(formula))
, и в среде run
(среде, в которой назначена формула) не назначен объект weights
, поэтому вместо него выдается stats::weights
.Три решения:
makeModel <- function(formula, weights) {
environment(formula) <- environment()
lm(formula, na.action = na.omit, weights = weights)
}
run<-function(x) {
f <- x$y ~ x$x + x$r
makeModel(f, x$size)
}
x1 <- run(x)
makeModel <- function(formula, weights) {
cl <- match.call()
cl[[1L]] <- quote(lm)
cl$na.action <- quote(na.omit)
eval(cl, parent.frame())
}
run<-function(x) {
f <- x$y ~ x$x + x$r
makeModel(f, x$size)
}
x2 <- run(x)
makeModel <- function(formula, weights, x) {
cl <- match.call()
cl[[1]] <- quote(lm)
cl$x <- NULL
cl[c("data", "formula", "na.action")] <-
list(quote(x), formula, quote(na.omit))
eval(cl)
}
run<-function(x) {
f <- y ~ x + r
makeModel(f, size, x)
}
x3 <- run(x)
stopifnot(all.equal(coef(x1), coef(x2)))
stopifnot(all.equal(coef(x1), coef(x3), check.attributes = FALSE))
. В качестве примера, первое решение, приведенное выше, подразумевает, что
eval(list(weights = weights), environment(formula), environment(formula))
успешен, поскольку в среде formula
назначен объект weights
.Второе решение делает вызов в среде run
с weights = x$size
и, таким образом, успешно.Третий - как ответ Романа Луштрика , хотя его решение гораздо более чистое, чем третье, которое я предлагаю, если вы знаете, что аргумент weights
всегда является столбцом size
.Здесь вызывается
eval(list(weights = size), data, environment(formula))
, который работает, поскольку size
является столбцом в data
.