Based on this question:
Customize label element position in ggplot using gtable/grob
The answer by https://stackoverflow.com/users/5193830/valentin-%c8%98tefan was fantastic and I learnt a lot from it.
However I would like to apply editGrob to more than one gPaths at a time.
Code:
#Dependencies
require(ggplot2); require(grid); require(png); require(RCurl) ; require(dplyr)
#Data Wrangling
mpg <- mpg
mpg <- filter(mpg, manufacturer %in% c("volkswagen","ford","dodge","audi"))
#Create Facet ggplot
p = ggplot(mpg, aes(displ, cty)) + geom_point() + facet_wrap(~manufacturer)
#Read in PNGs for Rastering
img = readPNG(system.file("img", "Rlogo.png", package = "png"))
#Function to Create annotations over initial ggplot
Create function
annotation_custom <-
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))}
#Apply annotation function referencing dataframe rows, combine initial plot
a1 = annotation_custom(rasterGrob(img, interpolate=TRUE), xmin=3, xmax=4, ymin=25, ymax=30, data=mpg[1,])
a2 = annotation_custom(rasterGrob(img, interpolate=TRUE), xmin=3, xmax=4, ymin=25, ymax=30, data=mpg[19,])
a3 = annotation_custom(rasterGrob(img, interpolate=TRUE), xmin=3, xmax=4, ymin=25, ymax=30, data=mpg[56,])
a4 = annotation_custom(rasterGrob(img, interpolate=TRUE), xmin=3, xmax=4, ymin=25, ymax=30, data=mpg[81,])
p1 <- p + a1 + a2 + a3 + a4
#Plot to show initial positions
p1
#Get all grobs and their components
g1A <- grid.force(ggplotGrob(p1))
#List the names of all grobs
grid.ls(g1A)
#Get all grob paths formatted
gpaths <- paste(gsub(pattern = "layout::",
replacement = "",
x = grid.ls(g1A, print = FALSE)$gPath),
grid.ls(g1A, print = FALSE)$name,
sep = "::")
#Choose specific grobs to alter
gpths <- gpaths[grepl("panel.*GRID.rastergrob*", gpaths)]
#Attempted Loop function for editgrob
loop_move_raster <- function(x,g){
for(i in seq_along(x)) {
edplot <- editGrob(grob = g,
gPath = x[[i]],
y = unit(-1.5, "cm"))
}
plot(edplot)
}
#Apply editgrob function to the grob paths required and plot the editted plot.
#Only last grob is updated.
loop_move_raster(x = gpths, g = g1A)
I have tried this by pulling the relevant grobs into a character vector and then applied a loop to try and update the grobs for each of the grob paths in the vector.
I know I could individually apply different positions to each image in the annotation_custom function but I want to be able to use the editgrob functionality as seen below in code, to apply changes to the grob as well as doing these all in one go through a loop.
As you can see the code runs fine but the output seems to be cycling through each grob and overwriting the output so only the final grob is edited with required alterations in the final plot.
Hoping this is a relatively straight forwards issue with my for-loop...