wake-up-neo.net

Verwendung von ggplot () innerhalb einer anderen Funktion in R

Ich versuche, eine einfache Plotfunktion zu schreiben, indem ich die Bibliothek ggplot2 verwende. Der Aufruf von ggplot findet das Funktionsargument jedoch nicht.

Stellen Sie sich einen data.frame namens means vor, der zwei Bedingungen und zwei Mittelwerte speichert, die ich darstellen möchte (Bedingung wird auf der X-Achse angezeigt, bedeutet auf dem Y).

library(ggplot2)
m <- c(13.8, 14.8)
cond <- c(1, 2)
means <- data.frame(means=m, condition=cond)
means
# The output should be:
#     means    condition
#   1 13.8     1
#   2 14.8     2

testplot <- function(meansdf)
{
  p <- ggplot(meansdf, aes(fill=meansdf$condition, y=meansdf$means, x = meansdf$condition))
  p + geom_bar(position="dodge", stat="identity")
}

testplot(means)
# This will output the following error:
# Error in eval(expr, envir, enclos) : object 'meansdf' not found

Es scheint also, dass ggplot eval aufruft, das das Argument meansdf nicht finden kann. Weiß jemand, wie ich das Funktionsargument erfolgreich an ggplot übergeben kann?

(Anmerkung: Ja, ich könnte einfach die ggplot-Funktion direkt aufrufen, aber ich hoffe, dass meine Plot-Funktion am Ende komplizierter wird! :))

40
trev

Da Joris und Chase bereits richtig geantwortet haben, ist es üblich, einfach den meansdf$-Teil wegzulassen und direkt auf die Datenrahmenspalten zu verweisen.

testplot <- function(meansdf)
{
  p <- ggplot(meansdf, 
              aes(fill = condition,
                  y = means,
                  x = condition))
  p + geom_bar(position = "dodge", stat = "identity")
}

Dies funktioniert, weil die in aes genannten Variablen entweder in der globalen Umgebung oder in dem an ggplot übergebenen Datenrahmen gesucht werden. Dies ist auch der Grund, warum Ihr Beispielcode - mit meansdf$condition usw. - nicht funktioniert hat: meansdf ist weder in der globalen Umgebung verfügbar, noch ist er innerhalb des an ggplot übergebenen Datenrahmens verfügbar, der meansdf selbst ist.


Die Tatsache, dass die Variablen in der globalen Umgebung statt in der aufrufenden Umgebung gesucht werden, ist tatsächlich ein bekannter Fehler in ggplot2 , den Hadley derzeit nicht für fixierbar hält .. Dies führt zu Problemen, wenn man möchte um eine lokale Variable zu verwenden, sagen wir scale, um die Daten für das Diagramm zu beeinflussen:

testplot <- function(meansdf)
{
  scale <- 0.5
  p <- ggplot(meansdf, 
              aes(fill = condition,
                  y = means * scale,   # does not work, since scale is not found
                  x = condition))
  p + geom_bar(position = "dodge", stat = "identity")
}

Eine sehr schöne Problemumgehung für diesen Fall wird von Winston Chang in der GitHub-Ausgabe bereitgestellt, auf die verwiesen wird: Den Parameter environment explizit auf die aktuelle Umgebung während des Aufrufs von ggplot..__ setzen.

testplot <- function(meansdf)
{
  scale <- 0.5
  p <- ggplot(meansdf, 
              aes(fill = condition,
                  y = means * scale,
                  x = condition),
              environment = environment())   # This is the only line changed / added
  p + geom_bar(position = "dodge", stat = "identity")
}

## Now, the following works
testplot(means)
34
jhin

Die "richtige" Möglichkeit, ggplot programmgesteuert zu verwenden, besteht darin, aes_string() anstelle von aes() zu verwenden und die Namen der Spalten als Zeichen und nicht als Objekte zu verwenden:

Für mehr programmatische Zwecke, zum Beispiel, wenn Benutzer möchten, dass Spaltennamen für verschiedene Ästhetiken als Argumente angegeben werden können, oder wenn diese Funktion in einem Paket enthalten ist, das R CMD CHECK ohne Warnungen über Variablennamen ohne Definition übergeben muss, können Sie aes_string() mit den benötigten Spalten als Zeichen.

testplot <- function(meansdf, xvar = "condition", yvar = "means",
                     fillvar = "condition") {
    p <- ggplot(meansdf,
                aes_string(x = xvar, y= yvar, fill = fillvar)) +
             geom_bar(position="dodge", stat="identity")
}
24
Gregor

Hier ist ein einfacher Trick, den ich häufig benutze, um meine Variablen in meiner Funktionsumgebung zu definieren (zweite Zeile): 

FUN <- function(fun.data, fun.y) {
    fun.data$fun.y <- fun.data[, fun.y]
    ggplot(fun.data, aes(x, fun.y)) + 
        geom_point() + 
        scale_y_continuous(fun.y)    
}

datas <- data.frame(x = rnorm(100, 0, 1),
                    y = x + rnorm(100, 2, 2),
                    z = x + rnorm(100, 5, 10))
FUN(datas, "y")
FUN(datas, "z")

Beachten Sie, wie sich die Bezeichnung der Y-Achse auch ändert, wenn verschiedene Variablen oder Datensätze verwendet werden.

18

Ich denke nicht, dass Sie den meansdf$-Teil in Ihren Funktionsaufruf selbst aufnehmen müssen. Das scheint auf meinem Rechner zu funktionieren:

meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)

testplot <- function(meansdf)
{
p <- ggplot(meansdf, aes(fill=condition, y=means, x = condition))
p + geom_bar(position="dodge", stat="identity")
}


testplot(meansdf)

produzieren:

enter image description here

16
Chase

Dies ist ein Beispiel für ein Problem, das früher behandelt wird. Grundsätzlich kommt es darauf an, dass ggplot2 hauptsächlich für die Verwendung in der globalen Umgebung codiert ist. Beim Aufruf von aes () wird nach den Variablen entweder in der globalen Umgebung oder innerhalb des angegebenen Datenrahmens gesucht.

library(ggplot2)
means <- data.frame(means=c(13.8,14.8),condition=1:2)

testplot <- function(meansdf)
{
  p <- ggplot(meansdf, aes(fill=condition, 
          y=means, x = condition))
  p + geom_bar(position="dodge", stat="identity")
}

BEARBEITEN:

update: Nachdem Sie die andere Antwort gesehen und das Paket ggplot2 aktualisiert haben, funktioniert der obige Code. Grund ist, wie in den Kommentaren erläutert, dass ggplot nach Variablen in aes in der globalen Umgebung (wenn der Datenrahmen speziell als meandf $ ... hinzugefügt wird) oder in der genannten Umgebung sucht.

Stellen Sie sicher, dass Sie mit der neuesten Version von ggplot2 arbeiten.

15
Joris Meys

Das hat mich einige Zeit frustriert. Ich wollte verschiedene Datenrahmen mit unterschiedlichen Variablennamen senden und wollte die Möglichkeit, verschiedene Spalten aus dem Datenrahmen zu zeichnen. Ich bekam schließlich eine Lösung, indem ich einige (globale) Dummy-Variablen für das Plotten und Erzwingen der Zuweisung innerhalb der Funktion erstellte

plotgraph function(df,df.x,df.y) {

dummy.df <<- df
dummy.x <<- df.x
dummy.y <<- df.y

p = ggplot(dummy.df,aes(x=dummy.x,y=dummy.y,.....)
print(p)

}

dann kann ich im main code einfach die funktion aufrufen

plotgraph(data,data$time,data$Y1)
plotgraph(data,data$time,data$Y2)
3

Sie brauchen nichts Besonderes. Nicht einmal Dummy-Variablen. Sie müssen nur ein print () in Ihre Funktion einfügen. Sie können mit cat () etwas in der Konsole anzeigen.

myplot <- ggplot (......) + Was auch immer Sie hier wünschen print (myplot) 

Es hat für mich mehr als einmal in derselben Funktion funktioniert

1
Perla Reyes

Kurze Antwort: Verwenden Sie qplot

Lange Antwort: Im Wesentlichen willst du so etwas wie:

my.barplot <- function(x=this.is.a.data.frame.typically) {
   # R code doing the magic comes here
   ...
}

Dies ist jedoch nicht flexibel, da Sie sich an eine konsistente Spaltenbenennung halten müssen, um die lästigen Eigenheiten des R-Bereichs zu vermeiden. Natürlich ist der nächste logische Schritt:

my.barplot <- function(data=data.frame(), x=..., y....) {
   # R code doing something really really magical here
   ...
}

Aber dann sieht das verdächtig aus wie ein Aufruf von qplot (), richtig?

qplot(data=my.data.frame, x=some.column, y=some.other column,
      geom="bar", stat="identity",...)

Natürlich möchten Sie jetzt Dinge wie Skalentitel ändern, aber dafür ist eine Funktion praktisch. Die gute Nachricht ist, dass Scoping-Probleme meistens weg sind.

my.plot <- qplot(data=my.data.frame, x=some.column, y=some.other column,...)
set.scales(p, xscale=scale_X_continuous, xtitle=NULL,
           yscale=scale_y_continuous(), title=NULL) {
  return(p + xscale(title=xtitle) + yscale(title=ytitle))
}
my.plot.prettier <- set.scale(my.plot, scale_x_discrete, 'Days',
                              scale_y_discrete, 'Count')
1
jcb

Eine andere Problemumgehung besteht darin, die aes (...) als Variable Ihrer Funktion zu definieren:

func<-function(meansdf, aes(...)){}

Das hat für mich zu einem ähnlichen Thema gut funktioniert

1
user3216394

Wenn es wichtig ist, die Variablen (Spaltennamen) an die benutzerdefinierte Plotierungsfunktion ohne Anführungszeichen zu übergeben, während andere Variablennamen innerhalb der Funktion verwendet werden, dann war eine andere Problemlösung, die ich ausprobierte, die Verwendung von match.call() und eval (wie hier auch): 

library(ggplot2)

meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)

testplot <- function(df, x, y) {
  arg <- match.call()
  scale <- 0.5
  p <- ggplot(df, aes(x = eval(arg$x),
                      y = eval(arg$y) * scale,
                      fill = eval(arg$x)))
  p + geom_bar(position = "dodge", stat = "identity")
}

testplot(meansdf, condition, means)

Erstellt am 10.01.2010 vom reprex-Paket (v0.2.1)

Eine andere Problemumgehung, bei der jedoch die Variablen in Anführungszeichen übergeben werden, verwendet get():

meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)

testplot <- function(df, x, y) {
  scale <- 0.5
  p <- ggplot(df, aes(x = get(x),
                      y = get(y) * scale,
                      fill = get(x)))
  p + geom_bar(position = "dodge", stat = "identity")
}

testplot(meansdf, "condition", "means")

Erstellt am 10.01.2010 vom reprex-Paket (v0.2.1)

0
Valentin

Ich generiere einfach neue Datenrahmenvariablen mit den gewünschten Namen in der Funktion:

testplot <- function(df, xVar, yVar, fillVar) {
    df$xVar = df[,which(names(df)==xVar)]
    df$yVar = df[,which(names(df)==yVar)]
    df$fillVar = df[,which(names(df)==fillVar)]
    p <- ggplot(df,
                aes(x=xvar, y=yvar, fill=fillvar)) +
             geom_bar(position="dodge", stat="identity")
    }
0
jhelvy