superponer - ¿Cómo dibujar líneas fuera del área de trazado en ggplot2?
superponer graficas en r ggplot (3)
Agregué las líneas / texto usando el código de este enlace: Usando grconvertX / grconvertY en ggplot2 . Este enfoque usa grid.text y grid.lines en lugar de grobs. No estoy seguro de qué enfoque es mejor.
Creo que grid.lines podría combinarse en la declaración de grid.polyline o posiblemente a través de un bucle. Las posiciones xey se pueden establecer en una variable en lugar de en la codificación rígida en cada línea.
La única complicación posible es pasar la báscula a la ventana gráfica. Sin embargo, siempre que se use la misma escala en GGPLOT y la ventana gráfica, este código debería funcionar. Tenga en cuenta que la ventana gráfica está usando toda la altura de la gráfica de 0 a 100.
library (ggplot2)
library(grid)
library(gridBase)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
qplot(subgroup, count,
data=test, geom="bar", stat="identity",
fill =category,
facets = .~ group, width=0.9)+
opts(legend.position="none", plot.margin = unit(c(0,9,2,0), "lines"))
current.vpTree()
downViewport(''panel-4-6'')
pushViewport(dataViewport( yscale=c(0,100), clip=''off'',xscale=c(0,1)))
grid.text(x=1.21, y = 90, default.units=''native'' ,label="Text 1")
grid.text(x=1.21, y = 55, default.units=''native'' ,label="Text 2")
grid.text(x=1.21, y = 10, default.units=''native'' ,label="Text 3")
grid.lines(x=c(1.02,1.12), y = c(95,95), default.units=''native'' )
grid.lines(x=c(1.02,1.12), y = c(85, 85), default.units=''native'' )
grid.lines(x=c(1.12,1.12), y = c(85, 95), default.units=''native'' )
grid.lines(x=c(1.02,1.12), y = c(80, 80), default.units=''native'' )
grid.lines(x=c(1.02,1.12), y = c(20, 20), default.units=''native'' )
grid.lines(x=c(1.12,1.12), y = c(80, 20), default.units=''native'' )
grid.lines(x=c(1.02,1.12), y = c(5, 5), default.units=''native'' )
grid.lines(x=c(1.02,1.12), y = c(15, 15), default.units=''native'' )
grid.lines(x=c(1.12,1.12), y = c(5, 15), default.units=''native'' )
Disculpas por cualquier problema de formato: simplemente pegué mi código y usé el botón de código para sangrarlo.
Creé esta trama con ggplot2 :
Las líneas exteriores deben corresponder a la escala Y, (es decir, la posición Y de las líneas para Text1 debe ser 100 y 85). La única forma en que puedo hacerlo es dibujar un diagrama en blanco a la derecha de la figura con la misma escala que el gráfico de barras y luego usar la función anotar para dibujar las líneas. Otro enfoque es simplemente dibujar "manualmente" las líneas con líneas de grid.lines
, sin embargo, las coordenadas de las grid.lines
de grid.lines
no se corresponderán con la escala Y de la gráfica.
¿Es posible dibujar de alguna manera estas líneas usando un enfoque diferente? Supongo que tendría que hacerse con grid.lines
. ¿Cómo podría pasar las coordinadas Y del gráfico de barras a grid.lines
?
A continuación se muestra el código mínimo utilizado para crear esta figura:
library (ggplot2)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
qplot(subgroup,
count,
data=test,
geom="bar",
stat="identity",
fill =category,
facets = .~ group, width=0.9)+
opts(legend.position="none",
plot.margin = unit(c(0,9,2,0), "lines"))
¿Cómo puedo dibujar las líneas a la derecha de las barras?
Recientemente, hice una pregunta sobre el dibujo de texto fuera del área de trazado en ggplot2 y la solución fue usar gt$layout
y grid.draw
.
Mostrando texto debajo del gráfico generado por ggplot2
¿Podría el enfoque similar ser utilizado aquí? Tengo entendido que annotation_custom es solo para texto y no funcionará con otros elementos gráficos. Gracias
Actualizar
La solución original utilizaba annotation_custom
, pero un problema con annotation_custom
es que dibuja la anotación en todos los paneles. Sin embargo, con una simple modificación, annotation_custom
puede dibujarse en un solo panel (tomado de la respuesta de Baptiste here )
annotation_custom2 <-
function (grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, data)
{
layer(data = data, stat = StatIdentity, position = PositionIdentity,
geom = ggplot2:::GeomCustomAnn,
inherit.aes = TRUE, params = list(grob = grob,
xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax))
}
library(ggplot2)
library(grid)
#Some data
test = data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
# base plot
p <- ggplot(test) +
geom_bar(aes(subgroup, count, fill = category), stat = "identity") +
facet_grid(. ~ group) +
theme(legend.position = "none",
plot.margin = unit(c(1,5,1,1), "lines"))
# Create the text Grobs
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
## Add the annotations
# Which panel to attach the annotations
data = data.frame(group=2)
# Text 1
p1 = p + annotation_custom2(Text1, xmin = 3., xmax = 3., ymin = 85, ymax = 100, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 100, ymax = 100, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 85, ymax = 85, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 85, ymax = 100, data = data)
# Text 2
p1 = p1 + annotation_custom2(Text2, xmin = 3, xmax = 3, ymin = 20, ymax = 80, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 80, ymax = 80, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 20, ymax = 20, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 20, ymax = 80, data = data)
# Text 4
p1 = p1 + annotation_custom2(Text4, xmin = 3, xmax = 3, ymin = 0, ymax = 15, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 15, ymax = 15, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 0, ymax = 0, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 0, ymax = 15, data = data)
# Code to override clipping
gt <- ggplotGrob(p1)
gt$layout[grepl("panel", gt$layout$name), ]$clip <- "off"
# Draw the plot
grid.newpage()
grid.draw(gt)
Solución Original
Creo que casi cualquier Grob creado usando grid()
se puede usar en annotation_custom()
. Puede haber formas más claras de hacerlo, pero aquí hay una manera de usar grid
, annotation_custom
y el código de @ baptiste desde aquí para anular el recorte (como en la publicación anterior).
library (ggplot2)
library(grid)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
## EDIT: Updated qplot() command
p <- qplot(subgroup, count,
data = test, geom = "bar", stat = "identity",
fill = category,
facets = .~ group, width = 0.9)+
theme(legend.position="none", plot.margin = unit(c(0,9,2,0), "lines"))
# Create the text Grobs
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
# Draw the plot
# Text 1
p1 = p + annotation_custom(grob = Text1, xmin = 3., xmax = 3., ymin = 85, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 100, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 85, ymax = 85) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 85, ymax = 100)
# Text 2
p1 = p1 + annotation_custom(grob = Text2, xmin = 3, xmax = 3, ymin = 20, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 80, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 20, ymax = 20) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 20, ymax = 80)
# Text 4
p1 = p1 + annotation_custom(grob = Text4, xmin = 3, xmax = 3, ymin = 0, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 15, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 0, ymax = 0) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 0, ymax = 15)
p1
# Code to override clipping
gt <- ggplot_gtable(ggplot_build(p1))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)
Las opts
actualizadas han quedado obsoletas; usa el theme
lugar.
Aquí hay otra solución. Soluciona el problema de annotation_custom()
grobs de annotation_custom()
custom) en ambos paneles. Dibuja dos gráficos: el primero es su diagrama de barras; el segundo contiene solo las anotaciones. Luego, los dos se combinan utilizando grid.arrange()
del paquete gridExtra
. Sin embargo, su problema con la polilínea permanece.
Todavía existe la cuestión de hacer que las escalas del eje y sean las mismas en las dos parcelas. Pero con cuidado, se puede hacer. En la gráfica que contiene las anotaciones, observe cómo los elementos que podrían tener un impacto en la escala del eje y no se eliminan (a través de theme_blank()
, sino que se ocultan (usando colour = NA
).
library(ggplot2)
library(gridExtra)
library(grid)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5))
# The bar plot
p1 <- ggplot(test, aes(subgroup, count, fill = category)) +
geom_bar(stat = "identity") +
facet_grid(.~ group) +
theme(legend.position = "none",
plot.margin = unit(c(1,0,2,0), "lines"))
p1 <- p1 + ylim(0, 100)
# The empty plot to contain the annotations
p2 = ggplot(data.frame(x = c(1,2), y = c(0,100), z = c(1,1)), aes(x,y)) + theme_bw() + facet_wrap(~ z) +
theme(axis.title.y = element_blank(),
axis.title.x = element_text(colour = NA),
axis.text.y = element_blank(),
axis.text.x = element_text(colour = NA),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.ticks = element_line(colour = NA),
panel.border = element_rect(colour = NA),
strip.background = element_rect(colour = NA, fill = NA),
strip.text.x = element_text(colour = NA),
plot.margin = unit(c(1,0,2,0), "lines"))
# The annotations
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
p2 = p2 + annotation_custom(grob = Text1, xmin = 1.4, xmax = 1.4, ymin = 85, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 100, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 85, ymax = 85) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 85, ymax = 100)
p2 = p2 + annotation_custom(grob = Text2, xmin = 1.4, xmax = 1.4, ymin = 20, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 80, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 20, ymax = 20) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 20, ymax = 80)
p2 = p2 + annotation_custom(grob = Text4, xmin = 1.4, xmax = 1.4, ymin = 0, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 15, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 0, ymax = 0) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 0, ymax = 15)
# Putting the two plots together
plot = arrangeGrob(p1, p2, ncol = 2, widths = unit(c(10, 2), c("null", "null")))
grid.draw(plot)