Come utilizzare una variabile per specificare il nome della colonna in ggplot


105

Ho un comando ggplot

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

all'interno di una funzione. Ma vorrei poter utilizzare un parametro della funzione per scegliere la colonna da utilizzare come colore e gruppo. Cioè vorrei qualcosa di simile

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

In modo che la colonna utilizzata in ggplot sia determinata dal parametro. Ad esempio per f ("majr") otteniamo l'effetto di

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

ma per f ("genere") otteniamo l'effetto di

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

Alcune cose che ho provato:

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

non ha funzionato. Nemmeno

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

Risposte:


161

Puoi usare aes_string:

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

fintanto che passi la colonna alla funzione come una stringa ( f("majr")anziché f(majr)). Si noti inoltre che abbiamo modificato le altre colonne "name"e "rate", in modo che siano stringhe.

Se per qualsiasi motivo preferisci non usarlo aes_string, puoi cambiarlo in (un po 'più ingombrante):

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

Vale la pena dire che non dovresti / non puoi fare aes_string(x = rates.by.groups$name..., e comunque non ne hai bisogno dato che hai già superato l' ggplot(data = rates.by.groups...argomento. (Il problema in questa domanda )
smci

3
Basta aggiungere una nota per indirizzare le persone alla risposta di Moody_Mudskipper con gli aggiornamenti per ggplot2 versione 3.0.0
Gregor Thomas,

@ buncis Non è vero, citando "column_name"o "column"non funzionerebbe
David Robinson

@DavidRobinson scusa il mio errore, non vedo che il codice è racchiuso in una funzione con parametro, cancellerò il mio commento
buncis

"ingombrante"? La valutazione non standard in R è ironicamente la "caratteristica" più ingombrante che abbia mai incontrato in un linguaggio di programmazione. Veramente esasperante.
jessexknight

44

Dalle note di rilascio di ggplot2 V3.0.0:

aes () ora supporta le quasiquotazioni in modo che tu possa usare !!, !!! e: =. Questo sostituisce aes_ () e aes_string () che ora sono leggermente deprecati (ma rimarranno in circolazione per molto tempo).

Il modo idiomatico ora sarebbe quello di convertire in un simbolo la stringa che la variabile contiene, usando sym()(che è quasi la stessa degli alias di base as.name()/ as.symbol()), e deselezionarla usando!!

Simulando i dati di OP possiamo fare:

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)

Se preferiamo fornire nomi grezzi alla funzione, possiamo fare:

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

Funzionerà con nomi noti anche come simboli E con stringhe letterali

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

Come dice Lionel su ensym():

ha lo scopo di imitare la sintassi degli argomenti in cui puoi fornire entrambi in LHS, ad esempio list (bare = 1, "quoted" = 2)


Una nota su enquo()

enquo()cita l'espressione (non necessariamente un simbolo) fornita all'argomento, non converte una stringa letterale in un simbolo in ensym()quanto potrebbe essere meno adattata qui, ma possiamo fare:

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
Questa roba ordinata è così fastidiosa. La documentazione da aes()sola parla enquo()ma non funziona. E chi ne ha mai sentito parlare ensym()prima? BIG SIGH
CoderGuy123

@Moody_Mudskipper For f2, tutti e quattro gli esempi funzionano, così come l'acquisizione del nome della colonna in una variabile (cioè aname <- "mjr"; f2(aname)). Se aggiungo codice per manipolare il data frame usando dplyr, tenta di trovare una colonna usando il nome della variabile e non la stringa nel nome della variabile. In altre parole, come mi metto rates.by.groups %>% group_by(!!column)...al lavoro e continuo a supportare i tre modi di chiamare f2?
steveb

1
"lo stesso ensymvale per l'acquisizione del nome della colonna in una variabile": non fallisce ma non restituisce lo stesso risultato, è progettato per gestire gli argomenti forniti come nomi e tollerare le virgolette attorno ad essi. Credo che vorresti trattare l'argomento come un nome e ripiegare sul valore se il nome non viene trovato. Questo è effettivamente ciò che accade con select, ma non con group_by... È possibile aggirarlo ma non è ovvio. Se è importante per te, penso che meriterebbe la sua stessa domanda.
Moody_Mudskipper

@Moody_Mudskipper Thanks. Stavo usando entrambi selecte group_byquindi questo era probabilmente il problema. Posso creare una nuova domanda, ma ho bisogno di trovare un semplice esempio e controllare per vedere se ha avuto risposta. Posso pubblicarlo in caso contrario.
steveb

Come usare !! in caso di facet_grid? Funziona con facet_grid(cols = vars(!!column))ma genera un errore confacet_grid(~ !!column)
mRiddle

14

Prova a usare aes_stringinvece di aes.


5
Questo è un ottimo consiglio, ma puoi spiegare loro perché? aes_string ti fa usare "" per le non variabili e usi le variabili senza virgolette. aes_string (x = "foo", y = "fee", group = variable)
mtelesha

@mtelesha forse perché la variabile ha una stringa come valore
buncis

10

Un'altra opzione ( ggplot2 > 3.0.0) consiste nell'usare il pronome di valutazione ordinata .dataper tagliare la variabile / colonna scelta dal rates.by.groupsframe di dati.

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)'))

Creato il 04/04/2019 dal pacchetto reprex (v0.2.1.9000)


0

L'uso aes_stringrisolve questo problema, ma affronta un problema quando si aggiungono barre di errore geom_errorbar. Di seguito è una semplice soluzione.

#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)

Bonus, puoi anche aggiungere sfaccettature alla tua trama usando queste linee all'interno del ggplot:

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

Questo script è stato modificato da questo post originale: ggplot2 - Barre di errore che utilizzano una funzione personalizzata


0

Ecco un esempio estremamente semplice.

Fai solo due cose

  1. Trasforma la stringa in un simbolo
  2. Aggiungi !!quando lo usi
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.