Verwendung einer Variablen zur Angabe des Spaltennamens in ggplot

105

Ich habe einen ggplot-Befehl

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

innerhalb einer Funktion. Ich möchte jedoch einen Parameter der Funktion verwenden können, um die Spalte auszuwählen, die als Farbe und Gruppe verwendet werden soll. Dh ich möchte so etwas

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

Damit wird die im ggplot verwendete Spalte durch den Parameter bestimmt. ZB für f ("majr") erhalten wir die Wirkung von

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

aber für f ("Geschlecht") erhalten wir die Wirkung von

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

Einige Dinge, die ich versucht habe:

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

funktioniert nicht. Noch tat

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

Antworten:

160

Sie können verwenden aes_string:

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

Solange Sie die Spalte als Zeichenfolge ( f("majr")und nicht f(majr)) an die Funktion übergeben . Beachten Sie auch, dass wir die anderen Spalten "name"und "rate"als Zeichenfolgen geändert haben .

Wenn Sie es aus irgendeinem Grund lieber nicht verwenden möchten aes_string, können Sie es in (etwas umständlicher) ändern:

    ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
                                        group=get(column) ) )
David Robinson
quelle
Es ist erwähnenswert, dass Sie es nicht tun sollten / können aes_string(x = rates.by.groups$name...und es auch nicht müssen, da Sie das ggplot(data = rates.by.groups...Argument bereits bestanden haben . (Das Problem in dieser Frage )
smci
3
Fügen Sie einfach eine Notiz hinzu, um die Leute auf Moody_Mudskippers Antwort mit Updates für ggplot2 Version 3.0.0
Gregor Thomas
@buncis Das ist nicht wahr, zitiert "column_name"oder "column"würde nicht funktionieren
David Robinson
@ DavidRobinson Entschuldigung mein Fehler, ich sehe nicht, dass der Code in eine Funktion mit Parameter eingeschlossen ist, werde meinen Kommentar löschen
Buncis
"schwerfällig"? Eine nicht standardmäßige Auswertung in R ist ironischerweise das umständlichste "Feature", das ich je in einer Programmiersprache gesehen habe. Wirklich verrückt.
Jessexknight
43

Aus den Versionshinweisen von ggplot2 V3.0.0:

aes () unterstützt jetzt die Quasiquotation, sodass Sie !!, !!! und: = verwenden können. Dies ersetzt aes_ () und aes_string (), die jetzt veraltet sind (aber noch lange bestehen bleiben).

Die idiomatische Möglichkeit wäre nun, die in der Variablen enthaltene Zeichenfolge mit sym()(die fast mit den Basisaliasen as.name()/ identisch ist) in ein Symbol zu konvertieren as.symbol()und sie mit zu entfernen!!

Wir können die Daten von OP simulieren:

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)

Wenn wir der Funktion lieber Rohnamen geben möchten, können wir Folgendes tun:

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

Es funktioniert mit Namen oder Symbolen UND mit String-Literalen

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

Wie Lionel sagt über ensym():

Es soll die Syntax von Argumenten imitieren, bei denen Sie beide in der LHS angeben können, z. B. Liste (bare = 1, "quote" = 2).


Ein Hinweis zu enquo()

enquo()zitiert den Ausdruck (nicht unbedingt ein Symbol), der dem Argument zugeführt wird. Es konvertiert kein Zeichenfolgenliteral in ein Symbol, so ensym()dass es hier möglicherweise weniger angepasst ist, aber wir können Folgendes tun:

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)
Moody_Mudskipper
quelle
12
Dieses ordentliche Zeug ist so nervig. Die Dokumentation für sich aes()selbst spricht darüber, enquo()aber es funktioniert nicht. Und wer hat schon mal davon gehört ensym()? BIG SIGH
CoderGuy123
@Moody_Mudskipper f2Alle vier Beispiele funktionieren, ebenso wie das Erfassen des Spaltennamens in einer Variablen (dh aname <- "mjr"; f2(aname)). Wenn ich Code hinzufüge, um den Datenrahmen damit zu bearbeiten, dplyrwird versucht, eine Spalte unter Verwendung des Variablennamens und nicht der Zeichenfolge im Variablennamen zu finden. Mit anderen Worten, wie komme ich rates.by.groups %>% group_by(!!column)...zur Arbeit und unterstütze trotzdem die drei Arten des Anrufens f2?
Steveb
1
"Dies ensymgilt auch für das Erfassen des Spaltennamens in einer Variablen": Es schlägt nicht fehl, gibt jedoch nicht das gleiche Ergebnis zurück. Es wurde entwickelt, um als Namen bereitgestellte Argumente zu verarbeiten und Anführungszeichen zu tolerieren. Ich glaube, Sie möchten das Argument als Namen behandeln und auf den Wert zurückgreifen, wenn der Name nicht gefunden wird. Dies ist eigentlich das, was passiert select, aber nicht mit group_by... Es ist möglich, es zu umgehen, aber nicht offensichtlich. Wenn es Ihnen wichtig ist, denke ich, hätte es eine eigene Frage verdient.
Moody_Mudskipper
@Moody_Mudskipper Danke. Ich habe beide verwendet selectund group_bydas war wahrscheinlich das Problem. Ich kann eine neue Frage erstellen, muss jedoch ein einfaches Beispiel erstellen und prüfen, ob es beantwortet wurde. Ich kann es posten, wenn nicht.
Steveb
Wie benutzt man !! im Falle von facet_grid? Es funktioniert mit facet_grid(cols = vars(!!column)), wirft aber einen Fehler mitfacet_grid(~ !!column)
mRiddle
14

Versuchen Sie es mit aes_stringanstelle von aes.

MDe
quelle
5
Dies ist ein guter Rat, aber können Sie ihnen sagen, warum? Mit aes_string verwenden Sie "" für Nichtvariablen und Variablen ohne Anführungszeichen. aes_string (x = "foo", y = "Gebühr", Gruppe = Variable)
mtelesha
@mtelesha vielleicht, weil die Variable Zeichenfolge als Wert hat
buncis
9

Eine andere Option ( ggplot2 > 3.0.0) besteht darin, das ordentliche Bewertungspronomen zu verwenden .data, um die ausgewählte Variable / Spalte aus dem rates.by.groupsDatenrahmen zu entfernen.

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

Erstellt am 04.04.2019 durch das reprex-Paket (v0.2.1.9000)

Tung
quelle
0

Die Verwendung aes_stringbehebt dieses Problem, tritt jedoch beim Hinzufügen von Fehlerbalken auf geom_errorbar. Unten finden Sie eine einfache Lösung.

#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, Sie können Ihrem Plot auch Facetten hinzufügen, indem Sie diese Linien im ggplot verwenden:

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

Dieses Skript wurde von diesem ursprünglichen Beitrag geändert: ggplot2 - Fehlerbalken mit einer benutzerdefinierten Funktion

Marty999
quelle
0

Hier ist ein extrem einfaches Beispiel.

Mach einfach zwei Dinge

  1. Verwandle die Zeichenfolge in ein Symbol
  2. Fügen !!Sie hinzu, wenn Sie es verwenden
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
stevec
quelle