ggplot2 - anota fuera de la trama
Me gustaría asociar valores de tamaño de muestra con puntos en un gráfico. Puedo usar geom_text
para colocar los números cerca de los puntos, pero esto es complicado. Sería mucho más limpio alinearlos a lo largo del borde exterior de la parcela.
Por ejemplo, tengo:
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)
Lo que produce esta trama:
Preferiría algo más como esto:
Sé que puedo crear un segundo gráfico y usarlo grid.arrange
(al estilo de esta publicación ), pero sería tedioso determinar el espaciado de los textGrobs para alinearlos con el eje y. ¿Hay alguna forma más fácil de hacer esto? ¡Gracias!
Esto ahora es sencillo con ggplot2 3.0.0, ya que ahora el recorte se puede desactivar en los gráficos usando el clip = 'off'
argumento en funciones de coordenadas como coord_cartesian(clip = 'off')
o coord_fixed(clip = 'off')
. A continuación se muestra un ejemplo.
# 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
No es necesario que estés dibujando una segunda trama. Puede utilizar annotation_custom
para colocar grobs en cualquier lugar dentro o fuera del área de trazado. El posicionamiento de los grobs se realiza en términos de coordenadas de datos. Suponiendo que "5", "10", "15" se alinean con "cat1", "cat2", "cat3", se cuida el posicionamiento vertical de los textGrobs: las coordenadas y de sus tres textGrobs vienen dadas por Coordenadas y de los tres puntos de datos. De forma predeterminada, ggplot2
los clips se desplazan al área de trazado, pero el recorte se puede anular. Es necesario ampliar el margen pertinente para dejar espacio al grob. Lo siguiente (usando ggplot2 0.9.2) proporciona un gráfico similar al segundo gráfico:
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)
Solución más sencilla basada engrid
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"))