используя lm(my_formula) внутри [.data.table j

У меня есть привычка обращаться к столбцам data.table в j, даже когда мне это не нужно:

require(data.table)
set.seed(1); n = 10
DT <- data.table(x=rnorm(n),y=rnorm(n))

frm <- formula(x~y)

DT[,lm(x~y)]         # 1 works
DT[,lm(frm)]         # 2 fails
lm(frm,data=DT)      # 3 what I'll do instead

Я ожидал, что # 2 сработает, так как lm должен искать переменные в DT, а затем в глобальной среде... Есть ли элегантный способ заставить что-то вроде # 2 работать?

В этом случае я использую lm, который принимает аргумент «данные», поэтому № 3 работает просто отлично.

ИЗМЕНИТЬ Обратите внимание, что это работает:

x1 <- DT$x
y1 <- DT$y
frm1 <- formula(x1~y1)
lm(frm1)

и это тоже:

rm(x1,y1)
bah <- function(){
    x1 <- DT$x
    y1 <- DT$y
    frm1 <- formula(x1~y1)
    lm(frm1)
}
bah()

EDIT2. Однако это не удается, что иллюстрирует ответ @eddi

frm1 <- formula(x1~y1)
bah1 <- function(){
    x1 <- DT$x
    y1 <- DT$y
    lm(frm1)
}
bah1()

person Frank    schedule 11.10.2013    source источник
comment
Спасибо, @Арун. Это подсказало мне поиск, который я должен был сделать перед публикацией. Похоже, что на это ответили еще пару раз, кроме: stackoverflow.com/questions/14784048/ stackoverflow.com/questions/19001792/ Я думаю, мне следует пометить это как дубликат или удалить его. Я решу, когда Я просыпаюсь. Я надеялся каким-то образом изменить формулу, чтобы lm выглядел в нужном месте (вместо использования аргумента data=, который кажется неуклюжим внутри data.table), но похоже, что есть никто.   -  person Frank    schedule 11.10.2013
comment
Не уверен, что это подходит для вашего реального варианта использования, но следующее работает m <- quote(lm(x~y)); DT[,eval(m)].   -  person Josh O'Brien    schedule 11.10.2013
comment
он терпит неудачу, потому что x и y не используются в вашем j, и потому что обычно data.table использует только те столбцы, которые он может обнаружить (и потому что он может быть только таким умным, прежде чем стать всемогущим;)) - я не пробовал это пока, но я думаю, что если вы даже сделаете {x; y; lm(frm)}, это сработает. Может быть, здесь есть FR, чтобы использовать .SDcols для обозначения столбцов, используемых, даже если нет .SD   -  person eddi    schedule 11.10.2013
comment
@eddi Ну, они вроде как в моем j, в том смысле, что мой j ищет их ... Я попробовал то, что вы предложили, а также DT[,{x <- x;y <- y;lm(frm)}], но без костей. Да, было бы неплохо иметь возможность использовать .SDcols без .SD.   -  person Frank    schedule 11.10.2013
comment
j искать их — это очень абстрактное утверждение, требующее понимания на уровне ИИ того, что делает ваш j. Я немного удивлен, что явное использование x и y этого не сделало, должно быть, я неправильно понимаю основную проблему. Re FR: пожалуйста, добавьте это.   -  person eddi    schedule 11.10.2013
comment
а, теперь я вижу, это проблема, специфичная для lm - она ​​ищет эти переменные в среде формулы, поэтому добавление переменных в среду j (используя их каким-либо образом) не помогает, так как среда формулы .GlobalEnv здесь.   -  person eddi    schedule 11.10.2013
comment
@eddi Да, я как-то склонен винить в этом lm, но я не уверен, в чем именно он не соответствует. Я отредактировал пару примеров выше.   -  person Frank    schedule 11.10.2013


Ответы (1)


Как работает lm, он ищет переменные, используемые в среде предоставленной формулы. Поскольку вы создаете свою формулу в глобальной среде, она не будет выглядеть в среде j-выражения, поэтому единственный способ заставить точное выражение lm(frm) работать — это добавить соответствующие переменные в правильную среду:

DT[, {assign('x', x, environment(frm));
      assign('y', y, environment(frm));
      lm(frm)}]

Теперь, очевидно, это не очень хорошее решение, и предложения Аруна и Джоша намного лучше, и я просто помещаю их здесь для понимания проблемы.

редактировать Другим (возможно, более извращенным и довольно хрупким) способом было бы изменить окружение имеющейся формулы (я постоянно делаю это здесь, но вы можете вернуть его обратно или скопировать, а затем выполнить Это):

DT[, {setattr(frm, '.Environment', get('SDenv', parent.frame(2))); lm(frm)}]

Между прочим, здесь происходит забавная вещь: всякий раз, когда вы используете get в j-выражении, создаются все переменные (поэтому не используйте его, если можете избежать), и именно поэтому я не не нужно также каким-то образом использовать x и y, чтобы data.table знал, что эти переменные необходимы.

person eddi    schedule 11.10.2013
comment
Не то решение, которое кто-то захочет использовать, но почти то, что я искал. Спасибо! - person Frank; 11.10.2013
comment
Один из примеров функции, которая работает, а аналогичная оценка j — нет: expr <- expression(x1~y1); bah2 <- function(){ x1 <- DT$x; y1 <- DT$y; lm(eval(expr)); }; bah2(); DT[,lm(eval(expr))] - person Frank; 11.10.2013
comment
@Frank, если вы загрузите последнюю версию, это будет работать: expr <- quote(x ~ y); DT[, lm(eval(expr))] - см. это: stackoverflow.com/questions/15913832/ - person eddi; 11.10.2013