2013-01-19 5 views
5

Im Anschluss an eine aktuelle Frage von mine, ist dies ein bisschen anders und veranschaulicht das Problem vollständiger mit einfacheren Beispielen. Im Folgenden sind zwei Datensätze und drei Funktionen. Die erste zieht einige Punkte und einen Kreis wie erwartet:Vererbung der Ästhetik in ggplot2 0.9.3 & das Verhalten von annotation_custom

library("ggplot2") 
library("grid") 

td1 <- data.frame(x = rnorm(10), y = rnorm(10)) 

tf1 <- function(df) { # works as expected 
    p <- ggplot(aes(x = x, y = y), data = df) 
    p <- p + geom_point(color = "red") 
    p <- p + annotation_custom(circleGrob()) 
    print(p) 
} 

tf1(td1) 

Das nächste scheint für die genaue Probefläche zu fragen, aber der Code ist etwas anders. Es gibt keinen Fehler geben, aber nicht den Kreis zeichnen:

tf2 <- function(df) { # circle isn't draw, but no error either 
    p <- ggplot() 
    p <- p + geom_point(data = df, aes(x = x, y = y), color = "red")   
    p <- p + annotation_custom(circleGrob()) 
    print(p) 
    } 

tf2(td1) 

Schließlich beinhaltet dieses eine komplexere Ästhetik und gibt eine leere Ebene, wenn Sie versuchen, den Kreis zu erstellen:

td3 <- data.frame(r = c(rnorm(5, 5, 1.5), rnorm(5, 8, 2)), 
    f1 = c(rep("L", 5), rep("H", 5)), f2 = rep(c("A", "B"), 5)) 

tf3 <- function(df) { 
    p <- ggplot() 
    p <- p + geom_point(data = df, 
     aes(x = f1, y = r, color = f2, group = f2))  
# p <- p + annotation_custom(circleGrob()) # comment out and it works 
    print(p) 
    } 

tf3(td3) 

Jetzt , Ich vermute das Problem hier ist nicht der Code, aber mein Versagen, die inneren Abläufe von ggplot2 zu erfassen. Ich könnte sicher eine Erklärung dafür verwenden, warum der Kreis im zweiten Fall nicht gezeichnet ist und warum der Layer im dritten Fall leer ist. Ich suchte nach annotation_custom auf den Code und es hat eine festverdrahtet inherit.aes = TRUE, die ich denke, das Problem ist. Ich verstehe nicht, warum diese Funktion überhaupt eine Ästhetik braucht (siehe die Dokumentation dazu). Ich habe versucht, mehrere Möglichkeiten, um es zu überschreiben und setzen inherit.aes = FALSE, aber ich konnte den Namespace nicht vollständig durchdringen und es halten. Ich habe versucht, die von ggplot2 erstellten Objekte zu beschreiben, aber diese proto Objekte sind sehr tief verschachtelt und schwer zu entschlüsseln.

+0

warum einreichen dies nicht als eine neue Ausgabe auf der Github-Repository? – baptiste

+0

@baptiste Ich habe darüber nachgedacht, aber wollte es hier zuerst zeigen, ob es mein Missverständnis/falsche Erwartung war, da ich eine Geschichte davon habe. Ich werde morgen einreichen, es sei denn jemand kommt mit einer Erklärung (und da Sie über diese Dinge ziemlich gut informiert sind, bezweifle ich, dass irgendjemand es wird). Vielen Dank. –

+0

Ich poste dies in den ggplot2 Issue Tracker. –

Antwort

2

Um dies zu beantworten:

„Ich sehe nicht, warum diese Funktion jede Ästhetik überhaupt braucht“.

In der Tat brauchen annotation_custom x und y aes seine grob maßstäblich, und nach den native Einheiten zu verwenden. Im Grunde tat es dies:

x_rng <- range(df$x, na.rm = TRUE)       ## ranges of x :aes x 
    y_rng <- range(df$y, na.rm = TRUE)       ## ranges of y :aes y 
    vp <- viewport(x = mean(x_rng), y = mean(y_rng),    ## create a viewport 
       width = diff(x_rng), height = diff(y_rng), 
       just = c("center","center")) 
    dd <- editGrob(grod =circleGrob(), vp = vp)     ##plot the grob in this vp 

Um dies zu veranschaulichen, mich grob zu einem Dummy-Plot hinzufügen als Maßstab für meine grob verwendet. Die erste ist eine große Skala und die zweite ist eine kleine.

base.big <- ggplot(aes(x = x1, y = y1), data = data.frame(x1=1:100,y1=1:100)) 
base.small <- ggplot(aes(x = x1, y = y1), data = data.frame(x1=1:20,y1=1:1)) 

definiere ich meine grob, sehe ich die nativen Skalen für xmin verwenden, xmax, ymin, ymax

annot <- annotation_custom(grob = circleGrob(), xmin = 0, 
               xmax = 20, 
               ymin = 0, 
               ymax = 1) 

nun die Waage Unterschied (kleinen Punkt/großer Kreis) zwischen (base.big +annot) und (base.small + annot).

library(gridExtra) 
grid.arrange(base.big+annot, 
      base.small+annot) 

enter image description here

+0

Danke für Ihre Antwort. Ich verstehe den Code, den Sie geschrieben haben und warum er funktioniert, aber ich bin mir nicht sicher, wie er sich auf meine Frage bezieht. Der Grund dafür, dass ich keine Ästhetik brauche, ist der, dass die Funktion keine Ästhetik verwendet (klar aus der Dokumentation und dem Code). Sicherlich muss es skaliert werden, um dem VP zu entsprechen, aber das ist keine Ästhetik (das Problem könnte sein, dass ich diese Begriffe nicht richtig verwende). 'annotation_custom' verwendet' inherit.aes' (intern, kein Argument), aber wo es von mir erbt, ist mir unklar. –

+0

'x' und' y' haben Standardwerte, weshalb Sie sie nicht übergeben müssen. – baptiste

+0

Sie haben geschrieben: "Jetzt sehen Sie die Skalen Differenz (kleiner Punkt/großer Kreis) zwischen (base.big + annot) und (base.big + annot)." Ich nehme an, Sie wollten "(base.small + annot)" schreiben. Auch "Baszially" ist falsch geschrieben (dritte Zeile). –

Verwandte Themen