replacing elements of a ggplot inside a gtable: la

2019-05-10 16:21发布

I am learning to manipulate ggplot objects with gtable. [Here is a related question I asked: dismantling a ggplot with grid and gtable ]

The present issue is:

  1. how to take various axis elements from one gtable and place them into another gtable in replacement of existing elements? and in particular: replace the vertical grid lines (and corresponding tickmarks).

Below some code and figures.

# Data
df <- structure(list(Year = c(1950, 2013, 1950, 2013), Country = structure(c(1L, 
1L, 2L, 2L), .Label = c("France", "United States"), class = "factor"), 
Category = c("Hourly minimum wage", "Hourly minimum wage", 
"Hourly minimum wage", "Hourly minimum wage"), value = c(2.14, 
9.43, 3.84, 7.25), variable = c("France (2013 euros)", 
"France (2013 euros)", "United States (2013 dollars)", "United States (2013 dollars)"
), Unit = c("2013 euros", "2013 euros", "2013 dollars", "2013 dollars"
)), .Names = c("Year", "Country", "Category", "value", "variable", 
"Unit"), row.names = c(NA, 4L), class = "data.frame")

# Plot data with ggplot
library(ggplot2)
p1 <- ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
geom_line(size = 2, show_guide = FALSE) + 
geom_point(size = 4, show_guide = FALSE) +
theme(panel.grid.major.x = element_line(size = 1, colour = "darkgreen"), 
      panel.grid.minor.x = element_line(size = 1, colour = "darkgreen", linetype = "dotted")) +
theme(text = element_text(size = 20, colour = "darkgreen")) +
theme(axis.text = element_text(size = 20, colour = "darkgreen"))

Here is p1:

enter image description here

p2 <- ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
geom_line(size = 2, show_guide = FALSE) + 
geom_point(size = 4, show_guide = FALSE) +
theme(panel.grid.major.x = element_line(size = 1, colour = "darkred"), 
      panel.grid.minor.x = element_line(size = 1, colour = "darkred", linetype = "dotted")) +
theme(text = element_text(size = 20, colour = "darkred")) +
theme(axis.text = element_text(size = 20, colour = "darkred"))

Here is p2:

enter image description here

# replace the bottom axis of p1 with that of p2
library(gtable)
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))

# function to remove selected elements from gtables, keeping widths
gtable_grob_remove <- function (g, what = "guide-box") {
    require(gtable)
    matches <- c(grepl(pattern = what, g$layout$name))
    g$layout <- g$layout[!matches, , drop = FALSE]
    g$grobs <- g$grobs[!matches]
    return(g)
}

# replace "axis-b"
g <- g1
pos <- c(subset(g$layout, name == "axis-b", se = t:r))
g <- gtable_grob_remove(g, what = "axis-b")
g <- gtable_add_grob(g, g2$grobs[[which(g2$layout$name == "axis-b")]], 
    pos$t, pos$l, pos$b, pos$r, , name = "axis-b")

# replace "xlab"
pos <- c(subset(g$layout, name == "xlab", se = t:r))
g <- gtable_grob_remove(g, what = "xlab")
g <- gtable_add_grob(g, g2$grobs[[which(g2$layout$name == "xlab")]], 
    pos$t, pos$l, pos$b, pos$r, , name = "xlab")

grid.newpage()
grid.draw(g)

Here is p1 with some p2 elements:

enter image description here

g1 is green, g2 is red, I want the red bottom axis labels and vertical grid lines to replace the green ones.

I have been successful in identifying the axis labels and axis title, but I'm still looking for the vertical grid lines (and the axis tickmarks and the axis horizontal line too!). I imagine they are inside the panel, but how to access them and alter them?

In a previous comment, baptiste suggested names(ggplotGrob(p2)[["grobs"]][[4]][["children"]]) as a way to identify different elements. This returns:

names(ggplotGrob(p2)[["grobs"]][[4]][["children"]])
[1] "grill.gTree.843"           "GRID.polyline.828"        
[3] "geom_point.points.830"     "panel.border.zeroGrob.831"

However, I do not know how to take it from here. Also, the appended numbers, e.g. .843 change with every session, so I would like to find a way to not hardcode these numbers. Thanks for suggestions!

1条回答
闹够了就滚
2楼-- · 2019-05-10 17:06

based on the other answer, consider this,

# locate the children
grill1 <- grepl("grill", 
              names(g1[["grobs"]][[4]][["children"]]))
grill2 <- grepl("grill", 
                names(g2[["grobs"]][[4]][["children"]]))

# swap the kids, the parents won't notice
g1[["grobs"]][[4]][["children"]][grill1] <- 
  g2[["grobs"]][[4]][["children"]][grill2]


grid.newpage()
grid.draw(g1)

enter image description here

查看更多
登录 后发表回答