R & quosures - Как получить имена символов, содержащихся в векторе, передаваемых в качестве аргумента функции? - PullRequest
0 голосов
/ 31 августа 2018

Я хочу написать функцию R arg2str, которая возвращает имена (то есть вектор строк) символов, которые передаются в качестве аргументов.

В самом простом случае у меня только один входной символ:

library ("rlang")

arg2str.v0 <- function (arg) rlang::quo_name (enquo (arg))
arg2str.v0 (a)
## [1] "a"

Если у меня несколько символов, я могу использовать конструкцию из трех точек:

arg2str.v1 <- function (...) sapply (enquos (...), rlang::quo_name)
arg2str.v1 (a, b, c)
##             
## "a" "b" "c"

(Вспомогательный вопрос: почему результирующий вектор строк отображается с предварительным переносом строки вместо предварительного [1] в этом случае?)

Но я действительно хочу иметь дело с векторами символов. Тем не менее:

sym2str.v1 (c(a, b, c))
##
## "c(a, b, c)"

Как мне настроить мою функцию для этого?


Моей первой интуицией было сначала заключить в кавычки символы, содержащиеся в векторе аргументов, используя sapply (вместо того, чтобы использовать сам вектор аргументов), а затем применить rlang::quo_name к результирующему вектору фраз. Но кажется, что символы в векторе аргументов вычисляются в пределах sapply до того, как enquote вызывается для каждого из них:

arg2str.v2 <- function (args) {
    enquo_args <- sapply (args, enquo)
    lapply (enquo_args, rlang::quo_name)
}
arg2str.v2 (c (a, b, c))
## Error in lapply(X = X, FUN = FUN, ...) : object 'a' not found

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Один возможный хакерский ответ с использованием substitute и deparse:

arg2str.v3 <- function (args) {
    strs <- sapply (substitute (args), deparse)
    if (length (strs) > 1) { strs <- strs [-1] }
    return (strs)
}
arg2str.v3 (c (a, b, c))
## [1] "a" "b" "c"

Обратите внимание, что он также сохраняет имена, если в качестве входных данных указан именованный вектор:

arg2str.v3 (c (n1 = a, n2 = b, n3 = c))
##  n1  n2  n3 
## "a" "b" "c"
0 голосов
/ 31 августа 2018

Я не уверен, есть ли векторизованная операция tidyeval для того, что вы хотите. Вы можете попробовать

f <- function(v) {
    v <- rlang::quo_name(enquo(v))
    gsub('^c\\(|\\s|\\)$', '', v) %>% 
        strsplit(',') %>% 
        unlist 
}

f(c(a, b, c))
#[1] "a" "b" "c"

, который будет работать с входами вида a, c(a) или c(a, b), но это немного хакерски ...

Ответ на дополнительный вопрос (почему arg2str.v1(a, b, c) не печатает "[1]" в начале строки) состоит в том, что он возвращает именованный вектор, имена которого являются пустыми строками (сравните, например, с выводом set_names(c('a', 'b', 'c'), c('', '', ''))).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...