Определение инфиксного оператора для использования в формуле

Я пытаюсь создать более экономную версию этого решения, которая влечет за собой указание RHS формулы в виде d1 + d1:d2,

При условии * в контексте формулы это содержательный заменитель полного взаимодействия (т.е. d1 * d2 дает d1 + d2 + d1:d2), мой подход был попытаться определить альтернативный оператор, скажем, %+:% используя инфиксный подход, к которому я привык в других приложениях, а именно:

"%+:%" <- function(d1,d2) d1 + d2 + d1:d2

Однако, это предсказуемо терпит неудачу, потому что я не был осторожен с оценкой; давайте представим пример, чтобы проиллюстрировать мой прогресс:

set.seed(1029)
v1 <- runif(1000)
v2 <- runif(1000)
y <- .8*(v1 < .3) + .2 * (v2 > .25 & v2 < .8) - 
  .4 * (v2 > .8) + .1 * (v1 > .3 & v2 > .8)

Надеемся, что в этом примере понятно, почему простое написание двух терминов может быть нежелательным:

y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
  cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3)

Один из способов, который близок к моему желаемому результату, - определить всю формулу как функцию:

plus.times <- function(outvar, d1, d2){
  as.formula(paste0(quote(outvar), "~", quote(d1),
                    "+", quote(d1), ":", quote(d2)))
}

Это дает ожидаемые коэффициенты при передаче lm, но с именами, которые труднее интерпретировать напрямую (особенно в реальных данных, где мы стараемся дать d1 а также d2 описательные имена, в отличие от этого общего примера):

out1 <- lm(y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
             cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3))
out2 <- lm(plus.times(y, cut(v2, breaks = c(0, .25, .8, 1)), I(v1 < .3)))
any(out1$coefficients != out2$coefficients)
# [1] FALSE
names(out2$coefficients)
# [1] "(Intercept)"         "d1(0.25,0.8]"        "d1(0.8,1]"           "d1(0,0.25]:d2TRUE"  
# [5] "d1(0.25,0.8]:d2TRUE" "d1(0.8,1]:d2TRUE"

Так что это менее чем оптимально.

Можно ли как-то настроить код так, чтобы упомянутый выше инфиксный оператор работал должным образом? Как насчет изменения формы plus.times чтобы переменные не переименовывались?

Я ковыряюсь (?formula, ?"~", ?":", getAnywhere(formula.default), этот ответ и т. д.), но не видел, как именно R интерпретирует * когда он встречается в формуле, чтобы я мог внести желаемые мелкие корректировки.

1 ответ

Решение

Вам не нужно определять новый оператор в этом случае: в формуле d1/d2 расширяется до d1 + d1:d2, Другими словами d1/d2 указывает, что d2 вложен в d1, Продолжая ваш пример:

out3 <- lm(y ~ cut(v2,breaks=c(0,.25,.8,1))/I(v1 < .3))
all.equal(coef(out1), coef(out3))
# [1] TRUE

Дальнейшие комментарии

Факторы могут быть пересечены или вложены. Два фактора пересекаются, если возможно наблюдать каждую комбинацию уровней двух факторов, например, пол и лечение, температуру и pH и т. Д. Фактор вкладывается в другой, если каждый уровень этого фактора можно наблюдать только в пределах одного из уровней. другого фактора, например, город и деревня, сотрудник, магазин и т. д.

Эти отношения отражаются в параметризации модели. Для скрещенных факторов мы используем d1*d2 или же d1 + d2 + d1:d2, чтобы дать основной эффект каждого фактора, а также взаимодействие. Для вложенных факторов мы используем d1/d2 или же d1 + d1:d2 дать отдельную подмодель формы 1 + d2 для каждого уровня d1,

Идея вложения не ограничивается факторами, например, мы можем использовать sex/x соответствовать отдельной линейной регрессии на x для мужчин и женщин.

В формуле %in% эквивалентно :, но это может использоваться, чтобы подчеркнуть вложенную или иерархическую структуру данных / модели. Например, a + b %in% a такой же как a + a:b, но, читая его как "плюс b внутри", дает лучшее описание модели, которая будет установлена. Несмотря на это, используя / имеет преимущество упрощения формулы модели в то же время, что и подчеркивание структуры.

Другие вопросы по тегам