R / nse / Двойная передача переменной подфункции - PullRequest
0 голосов
/ 15 января 2020

У меня есть две функции, которые я хочу обернуть вместе в функцию обертывания для удобства использования. Функция обтекания включает в себя переменную (имя столбца в кадре данных), которая должна быть передана из функции обтекания в одну из подфункций.

Сильно уменьшенный пример:

Подфункция 1: Создание данных

datafun <- function() {

    df_data <- data.frame(x = rep(1:20, 3), 
                          y = rnorm(60),
                          ga = sample(c("a", "b"), 30, replace = TRUE),
                          gb = sample(c("x", "y"), 20, replace = TRUE))

    df_data
}

Подфункция 2: Печать

plotfun <- function(df, gvar) {

    gvar_q = deparse(substitute(gvar))

    g <- ggplot2::ggplot(df, ggplot2::aes_string(x = "x", y = "y", color = gvar_q)) +
        ggplot2::geom_line() +
        directlabels::geom_dl(ggplot2::aes(label = {{gvar}}), method = list("last.points"))

    g
}

Функция обтекания

wrapfun <- function(gvar) {

    dat <- datafun()
    plot <- plotfun(df = dat, gvar = {{gvar}})

    plot
}

Тестирование

Использование двух подфункций напрямую работает без проблем:

#works
d <- datafun()
plotfun(d, gvar = ga)

Однако использование функции оборачивания приводит к ошибке

# doesn't work
wrapfun(gvar = ga)
>Error in FUN(X[[i]], ...) : object 'ga' not found

Обратите внимание, что (насколько я понял) directlabels::geom_dl не принимает aes_string в качестве обходного пути. Похоже, я не могу передать gvar как строку функции.

1 Ответ

1 голос
/ 15 января 2020

В последних версиях ggplot вы не используете deparse/substitute или aes_string. Вы используете новый синтаксис квазинотации исключительно. В этом примере вы должны сделать только

plotfun <- function(df, gvar) {

   ggplot2::ggplot(df, ggplot2::aes(x = x, y = y, color = {{gvar}})) +
     ggplot2::geom_line() +
     directlabels::geom_dl(ggplot2::aes(label = {{gvar}}), method = list("last.points"))

}

Тогда ваша функция будет работать как напрямую, так и в пределах wrapfun()

...