Afficher le texte en dessous du graphe généré par ggplot2

j'essaie d'afficher quelques informations sur les données sous le graphe créé dans ggplot2 . Je voudrais tracer la variable N en utilisant la coordonnée de l'axe X de la parcelle, mais la coordonnée Y doit être de 10% à partir du bas de l'écran . En fait, les coordonnées Y désirées sont déjà dans la base de données en tant que variable y_pos.

je peux penser de 3 approches à l'aide de ggplot2 :

1) Créer un graphique vide sous le graphique réel, Utilisez la même échelle et utilisez ensuite geom_text pour tracer les données sur le graphique vide. Cette approche genre de travaux, mais il est extrêmement compliqué.

2) Utilisez geom_text pour tracer les données, mais utilisez en quelque sorte la coordonnée y comme pourcentage de l'écran (10%). Cela forcerait les nombres à être affichés sous le graphe. Je ne peux pas comprendre la syntaxe correcte.

3) utiliser la grille.texte pour afficher le texte. Je peux il est facile de le régler à 10% à partir du bas de l'écran, mais je ne vois pas comment régler le x coordindate pour qu'il corresponde au graphe. J'ai essayé d'utiliser grconvert pour capturer la première position X, mais ne pouvait pas obtenir que cela fonctionne ainsi.

ci-dessous est le tracé de base avec les données fictives:

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

le gplot modifié ci-dessous affiche le nombre de sujets, mais ils sont affichés dans le graphique. Ils obligent à étendre l'échelle de Y. Je voudrais afficher ces numéros en contrebas de la parcelle.

    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( plot.margin = unit(c(0,2,2,1), "lines"),
        legend.position=c(.1,0.9))+
  geom_text(data = test,aes(x=x,y=y_pos,label=n))

p1

une autre façon d'afficher les chiffres consiste à créer un tracé fictif sous le tracé réel. Voici le 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 )

cependant, cela est très compliqué et serait difficile à modifier pour des données différentes. Idéalement, j'aimerais pouvoir passer les coordonnées Y en pourcentage de l'écran.

32
demandé sur Cœur 2012-04-04 19:21:53

4 réponses

révisé opts a été déprécié, remplacé par theme ; element_blank a remplacé theme_blank ; et ggtitle() est utilisé à la place de opts(title = ...

Sandy - merci beaucoup!!!! C'est exactement ce que je veux. J'aimerais qu'on puisse contrôler la coupure dans geom.texte ou geom.annoter.

j'ai mis en place le programme suivant si quelqu'un d'autre est intéressé.

 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

20
répondu Max C 2015-04-27 01:39:11

la version actuelle (>2.1) a un + labs(caption = "text") , qui affiche une annotation au-dessous de la parcelle. C'est personnalisable avec des thèmes (les propriétés de la police,... gauche/droite aligné). Voir https://github.com/hadley/ggplot2/pull/1582 par exemple.

16
répondu Jan Katins 2016-12-20 09:45:29

mis à jour opts() a été remplacé par theme()

dans le code ci-dessous, un tracé de base est tiré, avec une marge plus large au bas du tracé. Le textGrob est créé, puis inséré dans la parcelle en utilisant annotation_custom(). Sauf que le texte n'est pas visible parce qu'il est à l'extérieur de la parcelle panneau de sortie est coupée au panneau. Mais en utilisant le code de baptiste d'ici , la coupure peut être dépassée. La position est en termes d'unités de données, et les deux étiquettes de texte sont centrées.

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

ou, en utilisant les fonctions grid pour créer et positionner l'étiquette.

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

Modifier Ou, ajouter grob texte en utilisant des fonctions gtable.

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

15
répondu Sandy Muspratt 2017-05-23 10:31:25

en fait, la meilleure réponse et la solution la plus facile est d'utiliser le paquet cowplot.

Version 0.5.0 du paquet cowplot (sur CRAN) gère les sous-titres ggplot2 en utilisant la fonction add_sub.

utilisez - le comme ceci:

  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."))
5
répondu Taylor C. White 2016-01-04 02:10:18