Як використовувати змінну, щоб вказати ім'я стовпця в ggplot


105

У мене є команда 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 )

Відповіді:


161

Ви можете використовувати 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) ) )

Варто сказати, що ви не повинні / не можете цього робити aes_string(x = rates.by.groups$name..., і все одно вам цього не потрібно, оскільки ви вже передали ggplot(data = rates.by.groups...аргумент. (Проблема в цьому питанні )
smci

3
Просто додавши примітку, щоб вказати людей на відповідь Moody_Mudskipper з оновленнями для ggplot2 версії 3.0.0
Грегор Томас

@buncis Це неправда, цитуючи "column_name"або "column"нічого не вийде
Девід Робінсон

@DavidRobinson Вибачте за мою помилку, я не бачу, що код закріплений на функції з параметром,
видаляю

"громіздкий"? Нестандартне оцінювання на R - це, за іронією, найбільш громіздка "особливість", яку я коли-небудь стикався з мовою програмування. Воістину божевільний.
jessexknight

44

З випуску нот в ggplot2 V3.0.0:

aes () тепер підтримує квазіцитацію, щоб ви могли використовувати !!, !!!, і: =. Це замінює aes_ () та aes_string (), які тепер непридатні (але вони залишатимуться довгий час).

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

Моделюючи дані ОП, ми можемо:

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()
}

Він буде працювати з іменами aka символи ТА зі строковими буквами

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

Як каже Ліонель про ensym():

це призначено для імітації синтаксису аргументів, де ви можете подавати обидва в LHS, наприклад список (bare = 1, "quoted" = 2)


Примітка о enquo()

enquo()цитує вираз (не обов'язково символ), поданий до аргументу, він не перетворює рядковий літерал у символ, як 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)

12
Цей настирливий матеріал так дратує. Документація aes()сама по собі говорить, enquo()але вона не працює. А хто чув ensym()раніше? BIG SIGH
CoderGuy123

@Moody_Mudskipper Для f2, усі чотири приклади працюють, і так відбувається захоплення імені стовпця в змінній (тобто aname <- "mjr"; f2(aname)). Якщо я додаю код для маніпуляції кадром даних, використовуючи dplyrйого, він намагається знайти стовпець за допомогою імені змінної, а не рядка в імені змінної. Іншими словами, як я можу rates.by.groups %>% group_by(!!column)...працювати і все ще підтримувати три способи дзвінка f2?
steveb

1
"так відбувається захоплення імені стовпця змінною": вона не виходить з ладу, але не повертає той же результат, ensymпризначена для обробки аргументів, поданих у вигляді імен, і терпимо цитати навколо них. Я вважаю, що ви хочете трактувати аргумент як ім'я та повернутись до значення, якщо ім'я не знайдено. Це насправді те, що відбувається з select, але не з group_by... Можливо, зламати це, але не очевидно. Якщо для вас це важливо, я думаю, він би заслужив власне питання.
Moody_Mudskipper

@Moody_Mudskipper Дякую Я використовував і те, selectі group_byінше, ймовірно, проблема. Я можу створити нове запитання, але мені потрібно придумати простий приклад і перевірити, чи на нього відповіли. Я можу розмістити його, якщо ні.
steveb

Як використовувати !! у випадку facet_grid? Він працює, facet_grid(cols = vars(!!column))але видає помилку зfacet_grid(~ !!column)
mRiddle

14

Спробуйте використовувати aes_stringзамість aes.


5
Це чудова порада, але чи можете ви сказати їм, чому? aes_string змушує вас використовувати "" для не змінних, а ви використовуєте змінні котирування. aes_string (x = "foo", y = "гонорар", група = змінна)
mtelesha

@mtelesha можливо тому, що змінна має рядок як своє значення
buncis

10

Іншим варіантом ( ggplot2 > 3.0.0) є використання впорядкованого займенника, .dataщоб відрізати вибрану змінну / стовпчик з 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 пакетом reprex (v0.2.1.9000)


1

Використання aes_stringвиправляє цю проблему, але виникає проблема при додаванні рядків помилок geom_errorbar. Нижче просте рішення.

#Identify your variables using the names of your columns indie your dataset
 xaxis   <- "Independent"   
 yaxis   <- "Dependent"
 sd      <- "error"

#Specify error bar range (in 'a-b' not 'a'-'b')
 range   <- c(yaxis, sd)                                #using c(X, y) allows use of quotation marks inside formula
 yerrbar <- aes_string(ymin=paste(range, collapse='-'), 
                       ymax=paste(range, collapse='+'))


#Build the plot
  ggplot(data=Dataset, aes_string(x=xaxis, y=yaxis)) +
    geom_errorbar(mapping=yerrbar, width=15, colour="#73777a", size = 0.5) +
    geom_point   (shape=21)

Бонус, ви також можете додати грані до своєї ділянки, використовуючи ці рядки всередині ggplot:

facet_grid(formula(paste(Variable1, "~", Variable2)))

Цей скрипт було змінено з цієї оригінальної публікації: ggplot2 - Панелі помилок за допомогою спеціальної функції


0

Ось надзвичайно простий приклад.

Просто зробіть дві речі

  1. Перетворіть рядок у символ
  2. Додайте !!при використанні
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.