Как вы можете добавить (скажем, имя вектора) к объекту типа «формула» внутри функции? - PullRequest
1 голос
/ 15 декабря 2011

Это очень урезанная версия того, что я хочу сделать, я не могу вставить свою точную проблему, потому что код слишком длинный и сложный, но я думаю, что это является корнем проблемы. Благодаря ответу Джоша на этот вопрос Как вы кодируете функцию R, чтобы она «знала», как искать в «данных» переменные в других аргументах? Я отчасти здесь.

example <- function(model, xvar3=NULL, xvar4=NULL, data){
    print(class(model))
    #xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame())
    #xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame())
    print(class(xvar3))
    xvar5 <- xvar4^2
    mod <- glm( model + xvar3 + xvar5, data=data)    
    return(mod)
}

example(mpg ~ cyl, hp, wt, data=mtcars)

Это не удалось. Если вы удалите комментарии (основываясь на справке из предыдущего вопроса), это решит проблему «поиска» hp и wt. 'model' имеет формулу класса, и я хотел бы, чтобы она стала 'mpg ~ cyl + xvar3 + xvar5', чтобы glm работал. Но я не могу добавить их в формулу.

Я играл с классами 'call', а затем с 'eval' и 'as.formula' с вариациями 'paste' и 'noquote' и т. Д., Но не вижу, чтобы это стало возможным. 1008 *

Ответы [ 3 ]

2 голосов
/ 15 декабря 2011

Вот один из способов.Уловка, которую я использовал, заключается в создании новой формулы на основе заданной + двух дополнительных переменных.Затем я проделал трюк со средой формулы, чтобы можно было использовать как xvar3 / xvar5, так и любые переменные, локальные для вызывающего.данные для переменных (и больше нигде!).Вот почему среда формулы должна немного манипулировать в этом случае: она содержит xvar3 и xvar5, а родительская среда установлена ​​на среду исходной формулы, так что она также ищет переменные (foo в последнемпример) ...

example <- function(model, xvar3=NULL, xvar4=NULL, data){
    e <- new.env(parent=environment(model))
    e$xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame())
    e$xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame())
    e$xvar5 <- e$xvar4^2

    model <- update(model, . ~ . + xvar3 + xvar5)
    environment(model) <- e

    mod <- glm(model, data=data)

    return(mod)
}

example(mpg ~ cyl, hp, wt, data=mtcars)

# Using a local variable should work too:
doit <- function(d) {
   foo <- d$cyl+1
   example(mpg ~ foo, hp, wt, data=d)
}
doit(mtcars)
1 голос
/ 16 декабря 2011

Вот как бы я это сделал:

add_vars <- function(model, xvar3=NULL, xvar4=NULL, data){
  # Capture the unevalated calls to xvar3 and xvar4
  xvar3 <- substitute(xvar3)
  xvar4 <- substitute(xvar4)

  # Use substitute to create the correct formula to supply to update
  update_f <- eval(substitute(. ~ . + xvar3 + I(xvar4 ^ 2), 
    list(xvar3 = xvar3, xvar4 = xvar4)))

  # Modify the original formula string
  update(model, update_f)
}

add_vars(mpg ~ cyl, hp, wt)
# mpg ~ cyl + hp + I(wt^2)
0 голосов
/ 19 декабря 2011

Еще один вариант для этого (от коллеги):

example <- function(model, xvar3=NULL, xvar4=NULL, data){

    data$xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame())
    data$xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame())
    data$xvar5 <- data$xvar4^2

    model <- as.formula(paste(model[2], paste(model[3], "xvar4","xvar5", sep="+"), sep="~"))
    mod <- glm(model, data=data)
    return(mod)
}

example(mpg ~ cyl, hp, wt, data=mtcars)

Мне нравится, это довольно чисто.

...