Передача имени переменной в функцию из R
Я заметил, что довольно много пакетов позволяют передавать имена символов, которые могут быть даже недействительными в контексте вызова функции. Мне интересно, как это работает и как я могу использовать его в своем собственном коде?
Вот пример с ggplot2:
a <- data.frame(x=1:10,y=1:10)
library(ggplot2)
qplot(data=a,x=x,y=y)
x
и y
не существуют в моем пространстве имен, но ggplot понимает, что они являются частью фрейма данных и откладывает их оценку в контексте, в котором они действительны. Я пробовал сделать то же самое:
b <- function(data,name) { within(data,print(name)) }
b(a,x)
Однако это терпит неудачу:
Error in print(name) : object 'x' not found
Что я делаю неправильно? Как это работает?
Примечание: это не дубликат передать имя переменной функции в r
Ответы
Ответ 1
Я знаю, что это более старый поток, но это тот, о котором я упоминал в прошлом. Недавно я обнаружил, что, по моему мнению, лучший подход к передаче имен переменных. Поэтому я подумал, что я включу его. Надеюсь, это поможет кому-то.
a <- data.frame(x = 1:10, y = 1:10)
b <- function(df, name){
eval(substitute(name), df)
}
b(a, x)
[1] 1 2 3 4 5 6 7 8 9 10
Обновление. Этот подход использует нестандартную оценку. Я начал объяснять, но быстро понял, что Хэдли Уикхем делает это намного лучше, чем мог. Прочтите этот http://adv-r.had.co.nz/Computing-on-the-language.html
Ответ 2
Вы можете сделать это, используя match.call
, например:
b <- function(data,name) {
## match.call return a call containing the specified arguments
## and the function name also
## I convert it to a list , from which I remove the first element(-1)
## which is the function name
pars <- as.list(match.call()[-1])
data[,as.character(pars$name)]
}
b(mtcars,cyl)
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
объяснение:
match.call возвращает вызов, в котором все указанные аргументы указанных их полными именами.
Таким образом, вывод match.call
- 2 символа:
b <- function(data,name) {
str(as.list(match.call()[-1])) ## I am using str to get the type and name
}
b(mtcars,cyl)
List of 2
$ data: symbol mtcars
$ name: symbol cyl
Итак, я использую первый символ mtcars ansd преобразовать второй в строку:
mtcars[,"cyl"]
или эквивалент:
eval(pars$data)[,as.character(pars$name)]
Ответ 3
Если вы поместите имя переменной между кавычками, когда вы вызываете эту функцию, она работает:
> b <- function(data,name) { within(data,print(name)) }
> b(a, "x")
[1] "x"
x y
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
10 10 10