Передача несвязанных переменных в R-функции

#r #dplyr #arguments #interpreter

#r #dplyr #аргументы #интерпретатор

Вопрос:

 > counties %>% select(state, county, population, poverty)
> # also written as
> select(counties , state, county, population, poverty)
> state
Error: object 'state' not found
  

Всем привет,

У меня есть вопрос относительно того, что именно передается здесь в функцию select, state , county population и poverty на самом деле не являются переменными, привязанными к окружающей среде, а скорее именами столбцов первого элемента. Что делает аргументы, передаваемые в функцию, фактически отслеживающими состояние.

Как правило, на других языках эти ключи передавались бы в виде строки, поэтому мне просто интересно, как мы должны рассуждать и думать об этих несвязанных переменных здесь! И, возможно, дополнительно, как интерпретатор / анализатор R обрабатывает это под капотом.

Комментарии:

1. Ознакомьтесь с программированием с помощью виньетки dplyr

2. В ссылке на data.frame эти имена столбцов относятся к переменным. Если вы присоедините data.frame к вашей локальной среде, вы сможете ссылаться на них напрямую. Просто присоедините это с помощью attach(counties) , и вы можете использовать state в качестве имени переменной в локальной среде.

3. Обычно не рекомендуется использовать attach() , поскольку это может привести ко всевозможным ошибкам, главным образом потому, что это приводит к смешиванию пространств имен.

Ответ №1:

Это случай нестандартной оценки, специфичной для R. Это довольно мощная концепция в R и в основном означает, что то, что вы передаете в функции select , не вычисляется напрямую. Скорее, он принимает аргумент без оценки и вычисляет его позже, в контексте фрейма данных.

Я предлагаю вам прочитать об этом главу Advanced R http://adv-r.had.co.nz/Computing-on-the-language.html .

Чтобы подробнее остановиться на этом, посмотрите на этот пример, который демонстрирует основную концепцию:

 
expample_dataframe <- data.frame(
  foo = c(1:5),
  bar = c(10:14)
)

foo <- c("any" , "variable", "in", "global", "namespace")

print(foo) 
#> [1] "any"       "variable"  "in"        "global"    "namespace"

select_column <- function(data_frame, column_name){
  column_name <- substitute(column_name)
  eval(column_name, envir = data_frame)
}

select_column(expample_dataframe, foo)
#> [1] 1 2 3 4 5

foo
#> [1] "any"       "variable"  "in"        "global"    "namespace"
  

Объяснение

substitute() оставляет входные данные функции без оценки, т.е. ссылается на нее как на symbol . Затем мы можем использовать eval() функцию, которая позволяет вам вычислять определенный вызов / символ внутри определенного пространства имен. И да, в R фреймы данных — это пространства имен. Таким образом

eval(column_name, envir = data_frame) выполняется вычисление column_name в контексте фрейма данных.

Это то, что происходит за кулисами многих функций в R.

Создано 2020-08-14 пакетом reprex (версия 0.3.0)

Комментарии:

1. Спасибо, что указали мне правильное направление! Это именно то, что нужно! Хорошее напоминание о том, что аргументы функций также вычисляются лениво!!