web-dev-qa-db-fra.com

ggplot2 - annoter en dehors du tracé

Je voudrais associer des valeurs de taille d'échantillon à des points sur un tracé. Je peux utiliser geom_text pour positionner les nombres près des points, mais c'est désordonné. Il serait beaucoup plus propre de les aligner le long du bord extérieur de l'intrigue.

Par exemple, j'ai:

df=data.frame(y=c("cat1","cat2","cat3"),x=c(12,10,14),n=c(5,15,20))

ggplot(df,aes(x=x,y=y,label=n))+geom_point()+geom_text(size=8,hjust=-0.5)

Ce qui produit cette intrigue: enter image description here

Je préférerais quelque chose de plus comme ceci: enter image description here

Je sais que je peux créer un deuxième tracé et utiliser grid.arrange (à la ce post ) mais il serait fastidieux de déterminer l'espacement des textGrobs pour s'aligner avec l'axe des y. Existe-t-il un moyen plus simple de procéder? Merci!

59
jslefche

Vous n'avez pas besoin de dessiner un deuxième tracé. Vous pouvez utiliser annotation_custom pour positionner les grobs n'importe où à l'intérieur ou à l'extérieur de la zone de traçage. Le positionnement des grobs est en termes de coordonnées de données. En supposant que "5", "10", "15" s'alignent avec "cat1", "cat2", "cat3", le positionnement vertical des textGrobs est pris en charge - les coordonnées y de vos trois textGrobs sont données par le Coordonnées y des trois points de données. Par défaut, ggplot2 coupe les grobs dans la zone de traçage mais l'écrêtage peut être remplacé. La marge pertinente doit être élargie pour faire de la place pour le grob. Ce qui suit (en utilisant ggplot2 0.9.2) donne un tracé similaire à votre deuxième tracé:

library (ggplot2)
library(grid)

df=data.frame(y=c("cat1","cat2","cat3"),x=c(12,10,14),n=c(5,15,20))

p <- ggplot(df, aes(x,y)) + geom_point() +            # Base plot
     theme(plot.margin = unit(c(1,3,1,1), "lines"))   # Make room for the grob

for (i in 1:length(df$n))  {
p <- p + annotation_custom(
      grob = textGrob(label = df$n[i], hjust = 0, gp = gpar(cex = 1.5)),
      ymin = df$y[i],      # Vertical position of the textGrob
      ymax = df$y[i],
      xmin = 14.3,         # Note: The grobs are positioned outside the plot area
      xmax = 14.3)
 }    

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

enter image description here

55
Sandy Muspratt

C'est maintenant simple avec ggplot2 3.0.0, car maintenant l'écrêtage peut être désactivé dans les tracés en appelant coord_cartesian(clip = 'off'), comme dans l'exemple ci-dessous.

    # Generate data
    df <- data.frame(y=c("cat1","cat2","cat3"),
                     x=c(12,10,14),
                     n=c(5,15,20))

    # Create the plot
    ggplot(df,aes(x=x,y=y,label=n)) +
      geom_point()+
      geom_text(x = 14.25, # Set the position of the text to always be at '14.25'
                hjust = 0,
                size = 8) +
      coord_cartesian(xlim = c(10, 14), # This focuses the x-axis on the range of interest
                      clip = 'off') +   # This keeps the labels from disappearing
      theme(plot.margin = unit(c(1,3,1,1), "lines")) # This widens the right margin

enter image description here

32
bschneidr

Solution plus simple basée sur grid

require(grid)

df = data.frame(y = c("cat1", "cat2", "cat3"), x = c(12, 10, 14), n = c(5, 15, 20))

p <- ggplot(df, aes(x, y)) + geom_point() + # Base plot
theme(plot.margin = unit(c(1, 3, 1, 1), "lines"))

p

grid.text("20", x = unit(0.91, "npc"), y = unit(0.80, "npc"))
grid.text("15", x = unit(0.91, "npc"), y = unit(0.56, "npc"))
grid.text("5", x = unit(0.91, "npc"), y = unit(0.31, "npc"))
4
Stepan S. Sushko