tutorial - ¿Cómo puedo usar un gráfico importado con grImport como etiquetas de control de ejes en ggplot2(usando las funciones de cuadrícula)?
superponer graficas en r ggplot (3)
Espero poder combinar los grImport
poderes de importación y dibujo de grImport
con el increíble poder de ggplot2
, pero simplemente no entiendo el sistema de grid
suficiente como para encontrar una forma elegante de lograr lo que quiero. Lo que quiero es reemplazar las etiquetas de tilde del eje x en un gráfico ggplot2
con imágenes importadas usando grImport
.
Como ambos paquetes usan funciones de grid
, espero que haya una forma de usar grid.symbols()
dentro del marco ggplot2
, que sería ideal, o al menos en un gráfico existente en un dispositivo. ¿Alguien con más conocimiento de tales cosas sabe de una manera robusta de hacer esto? O, ¿alguien puede indicarme más información para ayudarme a aprender sobre grobs, viewports, etc.? He leído el capítulo libre del libro de gráficos R de Paul Murrel en el modelo de gráficos Grid, pero no estoy lo suficientemente familiarizado con el funcionamiento interno de ggplot2 para hacer el enlace.
Mi pregunta es muy similar a una pregunta existente sobre el uso de una imagen como punto de la trama , aunque estoy más interesado en las etiquetas del eje que en los puntos de la trama. Sin embargo, me gustaría saber qué tan similares son las dos tareas, y si esa solución puede adaptarse para este propósito. No pude resolverlo por mi cuenta.
Esta es mi primera publicación, por lo que no puedo publicar una imagen, pero este código logra algo parecido a lo que deseo. Nota: este enfoque utiliza un hack feo y feo que no es portátil y no es insatisfactorio. El último gráfico que quiero producir tendrá facetas ( facet_grid
), y el eje x es para un factor con diferentes imágenes en cada tic del eje , no una variable continua, por lo que estoy buscando una solución más general / robusta eso no requiere mucha prueba y error.
library(ggplot2)
## library(grImport) # not needed for this example, but would be for grid.symbols()
p <- ggplot(mtcars, aes(cyl, mpg)) + stat_summary(fun.data = "mean_cl_boot")
print(p)
## Replace (in this case, overlay) x-axis tick labels with a graphic / grob
iconSize <- 0.05
iconHt <- 0.2
padding <- 0.09 # horizontal padding around axis: I found this by trial & error
tickSp <- (1-padding)/(4*2)
downViewport("axis_h-5-3")
## I would use grid.symbols() with an imported Picture in place of grid.circle(),
## but the idea is the same: draw a shape at the ticks along the axis.
for (i in 0:(max(mtcars$cyl) - min(mtcars$cyl)) )
{
grid.circle(x = (padding/2 + tickSp*(i*2)), y = iconHt,
r = iconSize*(min(mtcars$cyl)+i), gp = gpar(fill="black"))
}
upViewport()
A continuación se muestra un truco para usar un grob personalizado para etiquetas de ejes.
library(grid)
library(ggplot2)
## convert the labels to some parameter to be used in the custom grob
## here simply an index that will be interpreted as color
mapping <- function(x, ...){
seq_along(x)
}
library(grImport)
hourglass <- new("Picture",
paths= list(new("PictureFill",
x=c(0, 1, 0, 1),
y=c(0, 0, 1, 1))),
summary= new("PictureSummary",
numPaths=1,
xscale=c(0, 1),
yscale=c(0, 1)))
## bare bones edit of theme_text()
my_axis <- function ()
{
structure(function(label, x = 0.5, y = 0.5, default.units = "npc", ...) {
cols <- mapping(label)
symbolsGrob(hourglass, x, 0*x + unit(0.5, "npc"),
use.gc=FALSE,size=unit(5,"mm"), gp=gpar(fill=cols))
}, class = "theme", type = "custom", call = match.call())
}
qplot(1:12, rnorm(12)) +
opts( axis.text.x = my_axis(), axis.ticks.margin = unit(0.5, "cm"))
Para un solo panel, es bastante sencillo extraer información del eje xx y reemplazarla por la suya. No estoy seguro de cómo esto podría extenderse limpiamente a ejes automáticos de paneles múltiples.
library(grid)
library(ggplot2)
p <- qplot(1:12, rnorm(12))
grid.newpage()
g <- ggplotGrob(p)
grid.draw(g)
g0 <- getGrob(g, gPath("axis.text.x"), grep=TRUE)
grid.set(gPath("axis.text.x"),
pointsGrob(x = g0$x, y=0*g0$x + unit(0.5,"npc"),
pch=19, gp=gpar(col=seq_along(g0$x)),
name = g0$name), grep = TRUE)
Aquí hay un ejemplo:
# convert ps to RGML
PostScriptTrace(file.path(system.file(package = "grImport"), "doc", "GNU.ps"), "GNU.xml")
PostScriptTrace(file.path(system.file(package = "grImport"), "doc", "tiger.ps"), "tiger.xml")
# read xml
pics <- list(a = readPicture("GNU.xml"), b = readPicture("tiger.xml"))
# custom function for x axis label.
my_axis <- function () {
structure(
function(label, x = 0.5, y = 0.5, ...) {
absoluteGrob(
do.call("gList", mapply(symbolsGrob, pics[label], x, y, SIMPLIFY = FALSE)),
height = unit(1.5, "cm"))
}
)}
qplot(factor(c("a", "b")), 1:2) + opts( axis.text.x = my_axis())