Подтвердить что ты не робот

Как использовать переменную для указания имени столбца в ggplot

У меня есть команда ggplot

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

внутри функции. Но я хотел бы иметь возможность использовать параметр функции для выбора столбца для использования в качестве цвета и группы. То есть Мне хотелось бы что-то вроде этого

f <- function( column ) {
    ...
    ggplot( rates.by.groups, aes(x=name, y=rate, colour= ??? , group=??? ) )
}

Итак, столбец, используемый в ggplot, определяется параметром. Например. для f ( "majr" ) получаем эффект

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

но для f ( "пол" ) мы получаем эффект

  ggplot( rates.by.groups, aes(x=name, y=rate, colour=gender, group=gender) )

Некоторые вещи, которые я пробовал:

ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ) )

не работает. Не

e <- environment() 
ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ), environment=e )
4b9b3361

Ответ 1

Вы можете использовать aes_string:

f <- function( column ) {
    ...
    ggplot( rates.by.groups, aes_string(x="name", y="rate", colour= column,
                                        group=column ) )
}

пока вы передаете столбец функции как строку (f("majr"), а не f(majr)). Также обратите внимание, что мы изменили другие столбцы, "name" и "rate", чтобы быть строками.

Если по какой-либо причине вы предпочитаете не использовать aes_string, вы можете изменить его на (несколько более громоздкий):

    ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
                                        group=get(column) ) )

Ответ 2

Из примечаний к выпуску ggplot2 V3.0.0:

aes() теперь поддерживает квазиквотацию, так что вы можете использовать !!, !!! и: =. Это заменяет aes_() и aes_string(), которые теперь мягко осуждаются (но останутся в течение долгого времени).

Теперь идиоматическим способом было бы преобразовать в символ строку, содержащуюся в переменной, используя sym (что почти совпадает с базовыми псевдонимами as.name/as.symbol), и заключить ее в кавычки, используя !!

Имитацию данных OP мы можем сделать:

library(tidyverse)
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4,4,5)],
  gender = c("M","F","F")
)

f <- function(column) {
  column <- sym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

f("gender")
f("mjr")
x <- "gender"
f(x)

Если бы мы предпочли передать необработанные имена в функцию, которую мы можем сделать:

f2 <- function(column) {
  column <- ensym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

Он будет работать с именами или символами AND и со строковыми литералами

f2(gender)
f2(mjr)
f2("gender")
f2("mjr")

Как говорит Лайонел о ensym:

это имитировало синтаксис аргументов, где вы можете указывать оба в LHS, например, list (bare = 1, "quoted" = 2)


Заметка на enquo

enquo кавычки выражение (не обязательно символ), enquo в аргумент, оно не преобразует строковый литерал в символ, как ensym делает ensym, поэтому оно может быть менее адаптировано здесь, но мы можем сделать:

f3 <- function(column) {
  column <- enquo(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

f3(gender)
f2(mjr)

Ответ 3

Попробуйте использовать aes_string вместо aes.

Ответ 4

Другой вариант (ggplot2 > 3.0.0) - использовать местоимение аккуратной оценки .data чтобы rates.by.groups выбранную переменную/столбец из rates.by.groups данных rates.by.groups.

library(ggplot2)
theme_set(theme_classic(base_size = 14))

# created by @Moody_Mudskipper
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4, 4, 5)],
  gender = c("M", "F", "F")
)

f1 <- function(df, column) {
  gg <- ggplot(df, 
         aes(x = name, 
             y = rate, 
             fill  = .data[[column]], 
             group = .data[[column]])) +
    geom_col() +
    labs(fill = column)
  return(gg)
}

plot_list <- lapply(list("gender", "mjr"), function(x){ f1(rates.by.groups, x) })
plot_list
#> [[1]]

#> 
#> [[2]]

# combine all plots
library(egg)
ggarrange(plots = plot_list,
          nrow = 2,
          labels = c('A)', 'B)'))

Создано 2019-04-04 пакетом представлением (v0.2.1.9000)