Почему вспомогательная функция tidyselect «where» может быть обнаружена внутри вспомогательной функции dplyr «поперек»?

#r #dplyr #tidyverse #tidyselect

#r #dplyr #tidyverse #tidyselect

Вопрос:

Пакет «tidyselect» предлагает вспомогательную функцию выбора where . where используется для выбора столбцов фрейма данных с помощью пользовательской функции. Это внутренняя функция из «tidyselect». Это означает where , что оно не будет загружено в ваше пространство имен, и вы можете вызвать его только с помощью tidyselect:::where .

Тем не менее, я видел следующий пример из виньеток dplyr: операции по столбцам.

 starwars %>% 
  summarise(across(where(is.character), ~ length(unique(.x))))
#> # A tibble: 1 x 8
#>    name hair_color skin_color eye_color   sex gender homeworld species
#>   <int>      <int>      <int>     <int> <int>  <int>     <int>   <int>
#> 1    87         13         31        15     5      3        49      38
  

В этом примере where написано без префикса «tidyselect:::», но очевидно, что в коде нет ошибок, и это дает значимый результат. Мне это кажется странным. Я хотел бы знать, почему код функционирует нормально.

Я предполагаю, что это связано с «цитированием кода», которое является частью методологии tidyeval. Грубо говоря, цитирование кода приостанавливает действие кодов как выражений и вычисляет выражения позже во «внутренней среде». Это всего лишь интуитивное предположение, и я не знаю, как его проверить.

Я надеюсь, что кто-нибудь сможет помочь мне с проблемой «где» или оставить несколько ссылок о том, как код функционирует для меня.

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

1. dplyr Пакет импортирует tidyselect пакет, поэтому функции tidyselect доступны для dplyr кода, но не привязаны к глобальному пути поиска.

2. @MrFlick Прошло некоторое время с тех пор, как я создавал свой последний пакет R, но afaik импорт пакета в файле описания только гарантирует, что пакет доступен. Если вы хотите использовать функции из нее, вам все равно нужно вызывать их по их полному имени — даже из внутреннего кода пакета.

3. @AEF Пользователю потребуется указать для функции пространство имен, но если пакет использует нестандартную оценку, пакет может оценивать эти символы в любой среде / пространстве имен, которые им нравятся. Таким образом, они могут передать недооцененное выражение соответствующей функции tidyselect, и tidyselect получит доступ ко всем функциям в своем пространстве имен.

Ответ №1:

Вы не сказали, какие пакеты прикреплены в вашем примере, но давайте предположим, что это единственный прикрепленный пакет dplyr .

 library(dplyr)
  

Во-первых, мы замечаем, что функция where не подключена, т. Е. Не известна текущему сеансу R. Мы можем проверить, просто введя ее имя (без круглых скобок) в консоли. Если бы функция была подключена, мы бы сейчас увидели ее исходный код. Вместо этого мы получаем сообщение об ошибке, что объект where не найден.

Однако мы отмечаем, что dplyr присоединяет другие функции из tidyselect , в starts_with качестве примера. Если мы повторим эксперимент с вводом имени в консоль, теперь мы увидим исходный код, а также то, что функции происходят из tidyselect пространства имен:

 > starts_with
function (match, ignore.case = TRUE, vars = NULL) 
{
    check_match(match)
    vars <- vars %||% peek_vars(fn = "starts_with")
    if (ignore.case) {
        vars <- tolower(vars)
        match <- tolower(match)
    }
    flat_map_int(match, starts_with_impl, vars)
}
<bytecode: 0x0000027338e5f8e8>
<environment: namespace:tidyselect>
  

В этом случае функция starts_with была присоединена dplyr с помощью NAMESPACE файла, в котором вы можете перечислить функции из других пакетов, которые должны быть присоединены вместе с вашим пакетом. Вы можете проверить dplyr исходный код.

Но where не становится доступным таким образом, как мы уже видели. В этом случае функция действительно заключена в кавычки и вычисляется только в пакете tidyselect. Если вы посмотрите на исходный код across, вы заметите, что в строке 82 спецификация столбца передается функции across_setup , определенной в том же файле. В этой функции спецификация столбца заключается в кавычки (строки 174, 175), а затем отправляется в tidyselect функцию tidyselect::eval_select (строка 177). Затем эта функция является частью пакета tidyselect и имеет к ней доступ where .

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

1.Хорошее объяснение! Было бы неплохо знать, почему where обрабатывается иначе, чем другие помощники выбора (т. Е. Не реэкспортируется), но, вероятно, это может исходить только от самих разработчиков.