Проблема не связана с вызовом apply()
. Это связано с тем, что вы используете x
в своей формуле, но набор данных, который вы передаете lm()
, не имеет столбца x
.
Функция lm()
немного «снисходительна», возможно, нежелательно. Если символ в данной формуле не может быть найден в данном наборе данных, то lm()
позволяет ему связываться с любой переменной, которая может быть найдена в цепочке окружения замыкания формулы. Из https://stat.ethz.ch/R-manual/R-devel/library/stats/html/model.frame.html:
Все переменные в формуле, подмножестве и в ... сначала ищутся в данных, а затем в среде формулы (дополнительные сведения см. В справке по формуле ()) и собираются во фрейм данных.
...
В рамку модели могут быть включены только переменные, тип которых является необработанным, логическим, целочисленным, действительным, сложным или символьным: сюда входят классифицированные переменные, такие как факторы (базовый тип которых целочисленный), но исключаются списки.
Теперь, на самом деле, обе ваши linear.f()
и lamda.f()
функции имеют параметр функции x
, и это позволяет выполнить вызов lm()
в обеих функциях. IOW, когда lm()
выполняется внутри этих функций, x
не может привязаться к какому-либо столбцу в данном наборе данных (data
), но затем привязывается к параметру функции в среде закрытия формулы (которая является средой оценки текущей функции оценка). Таким образом, вызов lm()
завершается успешно.
Более подробно: когда функция оценивается, ее параметры всегда сохраняются в среде оценки, которая создается для этой конкретной оценки этой конкретной функции. Поскольку вы определили формулу буквально внутри функции, она замыкается вокруг текущей среды оценки, и поэтому при запуске lm()
после неудачной попытки привязки к столбцу в наборе данных поиск цели для символа x
попадает в эту среду. first и привязывается к записи параметра функции в среде.
Я заметил, что вы указали, что однократный вызов верхнего уровня _17 _ + _ 18_ был успешным. Это любопытно, поскольку нет параметра функции для привязки. Я могу только догадываться, что в то время, когда вы запускали эту строку кода, в глобальной среде у вас была переменная x
, которая действительна для модели. В противном случае произойдет сбой, поскольку символ x
в формуле не имеет ничего, с чем можно было бы связываться ни в наборе данных, ни в цепочке среды закрытия. Обратите внимание, что lm()
должен завершиться ошибкой; Я даже не говорю о boxcox()
здесь:
if (exists('x')) rm(x); ## remove global x
lm(x~day+trt+day*trt,data=data);
## Error in eval(expr, envir, enclos) : object 'x' not found
Теперь, когда вы выполнили свой второй вызов apply, мы, вероятно, можем догадаться, что вы перезаписали глобальную переменную x
списком, что привело бы к точному сообщению об ошибке, которое вы получили:
x <- list();
lm(x~day+trt+day*trt,data=data);
## Error in model.frame.default(formula = x ~ day + trt + day * trt, data = data, :
## invalid type (list) for variable 'x'
Но здесь должно быть что-то еще. Вспомните, как я указывал, что и linear.f()
, и lamda.f()
имеют параметр функции x
, поэтому lm()
должен быть привязан к нему, и, поскольку это действительный вектор-предиктор, он должен быть успешным.
Мне кажется, что boxcox()
вызывает lm()
сам по себе и каким-то образом препятствует выполнению поиска цепочки замыканий в этом случае. Я считаю, что могу доказать эту гипотезу с помощью следующего кода, который использует IIFE (изначально JavaScript термин, но применимый к любому языку с первоклассными выражающими функциями, например R):
if (exists('x')) rm(x); ## remove global x
data2 <- data.frame(y=1:3); ## no x
(function(x) lm(y~x,data2))(1:3); ## x binds to function parameter
##
## Call:
## lm(formula = y ~ x, data = data2)
##
## Coefficients:
## (Intercept) x
## 0 1
##
(function(x) boxcox(lm(y~x,data2)))(1:3);
## Error in eval(expr, envir, enclos) : object 'x' not found
traceback();
## 14: eval(expr, envir, enclos)
## 13: eval(predvars, data, env)
## 12: model.frame.default(formula = y ~ x, data = data2, drop.unused.levels = TRUE)
## 11: stats::model.frame(formula = y ~ x, data = data2, drop.unused.levels = TRUE)
## 10: eval(expr, envir, enclos)
## 9: eval(mf, parent.frame())
## 8: lm(formula = y ~ x, data = data2, y = TRUE, qr = TRUE)
## 7: eval(expr, envir, enclos)
## 6: eval(call, parent.frame())
## 5: update.default(object, y = TRUE, qr = TRUE, ...)
## 4: update(object, y = TRUE, qr = TRUE, ...)
## 3: boxcox.lm(lm(y ~ x, data2))
## 2: boxcox(lm(y ~ x, data2)) at #1
## 1: (function(x) boxcox(lm(y ~ x, data2)))(1:3)
Как видите, похоже, что boxcox()
работает lm()
, но, в отличие от прямого вызова lm()
, не может выполнить привязку к параметру функции x
, даже если это должно быть возможно, поскольку аргумент формулы, переданный в boxcox()
, содержит указатель среды закрытия. Полагаю, мы могли бы списать это на слабость функции boxcox()
.
В любом случае, что касается решения, хорошим подходом было бы не зависеть от системы среды закрытия для разрешения несвязанных символов формулы, а вместо этого всегда обеспечивать, чтобы данный набор данных содержал столбцы для всех символов в формула. Простой пример:
data2 <- data.frame(y=1:3,x=10:12);
boxcox(lm(y~x,data2)); ## succeeds
Однако в вашем случае это не так просто, потому что у вас есть динамическая переменная результата. Хорошим подходом было бы дополнение вашего data.frame переменной результата непосредственно перед передачей ее в вызов lm()
, например с cbind(data,x)
.
К сожалению, и это удивительно, я получаю следующую ошибку:
lamda.f <- function(x) { data.x <- cbind(data,x); boxcox(lm(x~day+trt+day*trt,data=data.x))$x[which.max(boxcox(lm(x~day+trt+day*trt,data=data.x))$y)]; };
lamda.multiple <- apply(data[,4:ncol(data)],2,lamda.f);
## Error in is.data.frame(data) : object 'data.x' not found
Я даже попытался отделить вызов lm()
от вызова boxcox()
, на случай, если boxcox()
выполнил какую-то сумасшедшую нестандартную оценку своих аргументов и, таким образом, попытался оценить data.x
в контексте, который предотвратил бы привязку к среде оценки lamda.f()
:
lamda.f <- function(x) { data.x <- cbind(data,x); m <- lm(x~day+trt+day*trt,data=data.x); b <- boxcox(m); b$x[which.max(b$y)]; };
lamda.multiple <- apply(data[,4:ncol(data)],2,lamda.f);
## Error in is.data.frame(data) : object 'data.x' not found
Мне кажется, что boxcox()
очень сильно зависит от глобальной среды. Запуск boxcox()
изнутри области функции и в зависимости от каких-либо локальных переменных просто прерывает ее. Я подозреваю, что он проверяет вызов, хранящийся в объекте модели (например, m$call
), и пытается напрямую прочитать символы. В любом случае, это действительно странно.
Я думаю, вы можете решить эту проблему, сохранив дополненный data.frame в глобальной среде и убедившись, что он существует там в момент запуска boxcox()
. Для этого вы можете использовать оператор сверхназначения:
lamda.f <- function(x) { data.x <<- cbind(data,x); m <- lm(x~day+trt+day*trt,data=data.x); b <- boxcox(m); b$x[which.max(b$y)]; };
lamda.multiple <- apply(data[,4:ncol(data)],2,lamda.f);
lamda.multiple;
## X1 X2 X4 X7 X9
## 1.2323232 -0.6666667 0.7474747 -0.6666667 0.2222222
person
bgoldst
schedule
10.08.2015