2012-04-04 5 views
28

Ich versuche, einige Informationen zu den Daten unterhalb des Plots anzuzeigen, das in ggplot2 erstellt wurde. Ich möchte die N-Variable mit der Koordinate der X-Achse des Diagramms darstellen, aber die Y-Koordinate muss 10% vom unteren Rand des Bildschirms sein. Tatsächlich sind die gewünschten Y-Koordinaten bereits im Datenrahmen als Variable y_pos vorhanden.Anzeige von Text unterhalb des von ggplot2 generierten Plots

kann ich von 3 Ansätze denken ggplot2 mit:

1) Erstellen Sie ein leeres Grundstück unterhalb der eigentlichen Handlung, den gleichen Maßstab verwenden und dann geom_text verwenden, um die Daten über das leere Grundstück plotten. This approach Art von Arbeiten, ist aber sehr kompliziert.

2) Verwenden Sie geom_text, um die Daten zu plotten, aber irgendwie Y-Koordinate als Prozent des Bildschirms (10%) verwenden. Dies würde dazu führen, dass die Zahlen unterhalb des Diagramms angezeigt werden. Ich kann die richtige Syntax nicht herausfinden.

3) Verwenden Sie grid.text, um den Text anzuzeigen. Ich kann es leicht auf die 10% von der Unterseite des Bildschirms einstellen, aber ich kann nicht herausfinden, wie die X-Koordinate auf den Plot passt. Ich habe versucht, grconvert zu verwenden, um die anfängliche X-Position zu erfassen, aber ich konnte auch nicht so funktionieren.

Unten ist das Basisstück mit den Dummy-Daten:

graphics.off()  # close graphics windows 

library(car) 
library(ggplot2) #load ggplot 
library(gridExtra) #load Grid 
library(RGraphics) # support of the "R graphics" book, on CRAN 

#create dummy data 
test= data.frame(
    Group = c("A", "B", "A","B", "A", "B"), 
    x = c(1 ,1,2,2,3,3), 
    y = c(33,25,27,36,43,25), 
    n=c(71,55,65,58,65,58), 
    y_pos=c(9,6,9,6,9,6) 
) 

#create ggplot 
p1 <- qplot(x, y, data=test, colour=Group) + 
    ylab("Mean change from baseline") + 
    geom_line()+ 
    scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1)) + 
    opts( 
     legend.position=c(.1,0.9)) 

#display plot 
p1 

Das modifizierte gplot unten zeigt die Anzahl von Subjekten, aber sie innerhalb der Handlung angezeigt werden. Sie zwingen die Y-Skala zu verlängern. Ich möchte diese Zahlen unterhalb der Handlung anzeigen.

Ein anderer Ansatz zur Anzeige der Zahlen besteht darin, ein Dummy-Diagramm unterhalb der tatsächlichen Darstellung zu erstellen. Hier ist der Code:

graphics.off()  # close graphics windows 

library(car) 
library(ggplot2) #load ggplot 
library(gridExtra) #load Grid 
library(RGraphics) # support of the "R graphics" book, on CRAN 

#create dummy data 
test= data.frame(
    group = c("A", "B", "A","B", "A", "B"), 
    x = c(1 ,1,2,2,3,3), 
    y = c(33,25,27,36,43,25), 
    n=c(71,55,65,58,65,58), 
    y_pos=c(15,6,15,6,15,6) 
) 


p1 <- qplot(x, y, data=test, colour=group) + 
    ylab("Mean change from baseline") + 
    opts(plot.margin = unit(c(1,2,-1,1), "lines")) + 
    geom_line()+ 
    scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1)) + 
    opts(legend.position="bottom", 
     legend.title=theme_blank(), 
     title.text="Line plot using GGPLOT") 
p1 

p2 <- qplot(x, y, data=test, geom="blank")+ 
    ylab(" ")+ 
    opts( plot.margin = unit(c(0,2,-2,1), "lines"), 
      axis.line = theme_blank(), 
      axis.ticks = theme_segment(colour = "white"),   
      axis.text.x=theme_text(angle=-90,colour="white"), 
      axis.text.y=theme_text(angle=-90,colour="white"), 
      panel.background = theme_rect(fill = "transparent",colour = NA), 
      panel.grid.minor = theme_blank(),  
      panel.grid.major = theme_blank() 
      )+ 
    geom_text(data = test,aes(x=x,y=y_pos,label=n)) 
p2 

grid.arrange(p1, p2, heights = c(8.5, 1.5),    nrow=2) 
enter code here 

Allerdings ist das sehr kompliziert und wäre schwer für verschiedene Daten zu ändern. Im Idealfall möchte ich Y-Koordinaten als Prozent des Bildschirms übergeben können. Vielen Dank im Voraus!

+0

annotation_custom() und code [von hier] (http://stackoverflow.com/questions/9690648/point-clipped-on-x-axis-in-ggplot) könnte Ihnen helfen. Siehe unten. –

+0

Siehe meine Antwort unten. Es ist definitiv einfacher als die angenommene Antwort. –

+0

In den letzten Versionen von ggplot2 ist diese Funktion nun wie folgt integriert: http://stackoverflow.com/a/36036479/170352 –

Antwort

18

Editedopts ist veraltet, ersetzt durch theme; element_blank hat theme_blank ersetzt; und ggtitle() wird anstelle von opts(title = ...

Sandy verwendet- Vielen Dank !!!! Das macht genau das, was ich will. Ich wünschte, wir könnten das Clipping in geom.text oder geom.annotate kontrollieren.

Ich stelle das folgende Programm zusammen, wenn jemand anderes interessiert ist.

rm(list = ls())  # clear objects 
graphics.off()  # close graphics windows 

library(ggplot2) 
library(gridExtra) 

#create dummy data 
test= data.frame(
    group = c("Group 1", "Group 1", "Group 1","Group 2", "Group 2", "Group 2"), 
    x = c(1 ,2,3,1,2,3), 
    y = c(33,25,27,36,23,25), 
    n=c(71,55,65,58,65,58), 
    ypos=c(18,18,18,17,17,17) 

) 


p1 <- qplot(x=x, y=y, data=test, colour=group) + 
    ylab("Mean change from baseline") + 
    theme(plot.margin = unit(c(1,3,8,1), "lines")) + 
    geom_line()+ 
    scale_x_continuous("Visits", breaks=seq(-1,3)) + 
    theme(legend.position="bottom", 
     legend.title=element_blank())+ 
    ggtitle("Line plot") 


# Create the textGrobs 
for (ii in 1:nrow(test)) 
{ 
    #display numbers at each visit 
    p1=p1+ annotation_custom(grob = textGrob(test$n[ii]), 
          xmin = test$x[ii], 
          xmax = test$x[ii], 
          ymin = test$ypos[ii], 
          ymax = test$ypos[ii]) 

    #display group text 
    if (ii %in% c(1,4)) #there is probably a better way 
     { 
    p1=p1+ annotation_custom(grob = textGrob(test$group[ii]), 
          xmin = 0.85, 
          xmax = 0.85, 
          ymin = test$ypos[ii], 
          ymax = test$ypos[ii]) 
    } 

    } 




    # Code to override clipping 
    gt <- ggplot_gtable(ggplot_build(p1)) 
    gt$layout$clip[gt$layout$name=="panel"] <- "off" 
    grid.draw(gt) 

enter image description here

+1

Sehr schön !! Vergiss nicht, deine eigene Antwort zu akzeptieren. –

+0

Es sieht nicht richtig aus, funktioniert der Code noch für Sie? – PatrickT

13

Aktualisiertopts() hat mit theme()

In dem folgenden Code wird ein Basisstück gezogen wird, mit einem breiteren Rand am unteren Rand des Grundstücks ersetzt. Der TextGrob wird erstellt und dann mithilfe von annotation_custom() in den Plot eingefügt. Nur der Text ist nicht sichtbar, da er sich außerhalb des Plot-Bereichs befindet - der Output wird an das Panel geklammert. Mit dem Baptiste-Code from here kann das Clipping überschrieben werden. Die Position bezieht sich auf Dateneinheiten und beide Textbeschriftungen sind zentriert.

library(ggplot2) 
library(grid) 

# Base plot 
df = data.frame(x=seq(1:10), y = seq(1:10)) 
p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) + 
    theme(plot.margin = unit(c(1,1,3,1), "cm")) 
p 

# Create the textGrobs 
Text1 = textGrob(paste("Largest x-value is", round(max(df$x), 2), sep = " ")) 
Text2 = textGrob(paste("Mean = ", mean(df$x), sep = "")) 

p1 = p + annotation_custom(grob = Text1, xmin = 4, xmax = 4, ymin = -3, ymax = -3) + 
     annotation_custom(grob = Text2, xmin = 8, xmax = 8, ymin = -3, ymax = -3) 
p1 

# Code to override clipping 
gt <- ggplotGrob(p1) 
gt$layout$clip[gt$layout$name=="panel"] <- "off" 
grid.draw(gt) 

enter image description here

Oder grid Funktionen mit dem Label erstellen und zu positionieren.

p 
grid.text((paste("Largest x-value is", max(df$x), sep = " ")), 
    x = unit(.2, "npc"), y = unit(.1, "npc"), just = c("left", "bottom"), 
    gp = gpar(fontface = "bold", fontsize = 18, col = "blue")) 

enter image description here

bearbeiten Oder Text grob mit gtable Funktionen hinzuzufügen.

library(ggplot2) 
library(grid) 
library(gtable) 

# Base plot 
df = data.frame(x=seq(1:10), y = seq(1:10)) 
p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) 

# Construct the text grob 
lab = textGrob((paste("Largest x-value is", max(df$x), sep = " ")), 
    x = unit(.1, "npc"), just = c("left"), 
    gp = gpar(fontface = "bold", fontsize = 18, col = "blue")) 


gp = ggplotGrob(p) 

# Add a row below the 2nd from the bottom 
gp = gtable_add_rows(gp, unit(2, "grobheight", lab), -2) 

# Add 'lab' grob to that row, under the plot panel 
gp = gtable_add_grob(gp, lab, t = -2, l = gp$layout[gp$layout$name == "panel",]$l) 

grid.newpage() 
grid.draw(gp) 

enter image description here

+0

Vielen Dank !!! Ich weiß, dass Grid-Funktionen erlauben, Text irgendwo auf dem Gerät zu platzieren. Ich frage mich nur, ob es möglich ist, Text UNTER der Handlung zu platzieren, aber irgendwie die X-Koordinaten aus der Handlung zu verwenden. d. h. etwas, das dem ähnlich ist, was Sie mit der Textfunktion in der Basis R erreichen könnten. –

+0

Danke! Ich erhalte Fehler: konnte die Funktion "ggplot_gtable" nicht finden > gt $ layout $ clip [gt $ layout $ name == "panel"] <- "aus" –

+0

Es ist eine Funktion in 'ggplot2'. Welche Version von ggplot2 verwendest du? Möglicherweise müssen Sie ein Upgrade durchführen. Die neueste Version ist 0.9.0 –

5

Eigentlich die beste Antwort und einfachste Lösung ist es, das cowplot Paket zu verwenden.

Die Version 0.5.0 des Cowplot-Pakets (auf CRAN) verarbeitet die Untertitel ggplot2 mit der Funktion add_sub.

es wie so verwenden:

diamondsCubed <-ggplot(aes(carat, price), data = diamonds) + 
    geom_point() + 
    scale_x_continuous(trans = cuberoot_trans(), limits = c(0.2, 3), 
        breaks = c(0.2, 0.5, 1, 2, 3)) + 
    scale_y_continuous(trans = log10_trans(), limits = c(350, 15000), 
        breaks = c(350, 1000, 5000, 10000, 15000)) + 
    ggtitle('Price log10 by Cube-Root of Carat') + 
    theme_xkcd() 


    ggdraw(add_sub(diamondsCubed, "This is an annotation.\nAnnotations can span multiple lines.")) 
12

Die aktuelle Version (> 2.1) ein + labs(caption = "text") hat, der unter dem Grundstück eine Anmerkung anzeigt. Dies ist anpassbar (Schrifteigenschaften, ... links/rechts ausgerichtet). Beispiele finden Sie unter https://github.com/hadley/ggplot2/pull/1582.