У меня есть функция, которая выполняет M-тест Box для равенства ковариации матриц в многомерной линейной модели. Я хотел бы превратить его в общую функцию S3 с помощью метода формулы, который является наиболее естественным интерфейсом.Как написать метод формулы S3 для объекта статистической модели в R
Полный текущий код: https://gist.github.com/friendly/749b5a69a067e02b87dd. Я мог бы вставить все это здесь, но, возможно, достаточно ссылки .
Я не понимаю много магии, используемой в функциях, которые получают доступ к компонентам объекта модели. Я использовал в качестве шаблона код, который я нашел в leveneTest
в пакете car
, который решает аналогичную проблему для одномерных моделей.
Вот быстрый тест с использованием метода по умолчанию boxM.default
:
data(iris)
res <- boxM(iris[, 1:4], iris[, "Species"])
res
, которая дает желаемый результат:
> data(iris)
> res <- boxM(iris[, 1:4], iris[, "Species"])
> res
Box's M-test for Homogeneity of Covariance Matrices
data: iris[, 1:4]
Chi-Sq (approx.) = 140.94, df = 20, p-value < 2.2e-16
>
Когда я пытаюсь вызвать метод формулу boxM.formula
непосредственно, она также работает, давая тот же результат, что и выше.
boxM(cbind(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) ~ Species, data=iris)
Однако это испытание метода boxM.lm
не удается:
> iris.mod <- lm(cbind(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) ~ Species, data=iris)
> boxM(iris.mod)
Error in cbind(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) :
object 'Sepal.Length' not found
> traceback()
8: cbind(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)
7: eval(expr, envir, enclos)
6: eval(predvars, data, env)
5: model.frame.default(form, data)
4: model.frame(form, data) at boxM.R#59
3: boxM.formula(formula(y), data = model.frame(y), ...) at boxM.R#76
2: boxM.lm(iris.mod) at boxM.R#2
1: boxM(iris.mod)
>
Я думаю, что я понимаю, почему он не --- что-то делать с окружающей средой, для нахождения переменных в model.frame()
, но не как исправить это.
Может кто-нибудь помочь?
Это очень хорошее объяснение, и, возможно, я могу назвать 'boxM.default' напрямую. Коллега дал мне более общее решение. Я отправляю его как ответ ниже, чтобы заполнить эту тему. – user101089