Label the individual axes in bold using ggplot2

Question adapted from this question and solution: Highlighting individual axis labels in bold using ggplot2

I would like to selectively substantiate the labels of the horizontal axes depending on their compliance with the criteria. So, borrowing from the above question and answer, I created an example:

require(ggplot2) require(dplyr) set.seed(36) xx<-data.frame(YEAR=rep(c("X", "Y"), each=20), CLONE=rep(c("A", "B", "C", "D", "E"), each=4, 2), TREAT=rep(c("T1", "T2", "T3", "C"), 10), VALUE=sample(c(1:10), 40, replace=T)) # Simple plot with factors on y axis ggplot(xx, aes(x = VALUE, y=CLONE, fill=YEAR)) + geom_bar(stat="identity", position="dodge") + facet_wrap(~TREAT) 

enter image description here

So, I took a function from the above question + to create a vector of excuses:

 # Modify to control justification colorado2 <- function(src, boulder) { if (!is.factor(src)) src <- factor(src) src_levels <- levels(src) brave <- boulder %in% src_levels if (all(brave)) { b_pos <- purrr::map_int(boulder, ~which(.==src_levels)) b_vec <- rep(0.2, length(src_levels)) b_vec[b_pos] <- 0.9 b_vec } else { stop("All elements of 'boulder' must be in src") } } # Redraw the plot with modifcation ggplot(xx, aes(x = VALUE, y=CLONE, fill=YEAR)) + geom_bar(stat="identity", position="dodge") + facet_wrap(~TREAT) + theme(axis.text.y=element_text(hjust=colorado2(xx$CLONE, c("A", "B", "E")))) 

I get this miserable mess: enter image description here

The labels are justified in the direction I want, but taking up too much space for reasons that I cannot understand. How to fix it?

+5
source share
2 answers

I did digging. The problem is how ggplot sets the grob width of the y axis. hjust is assumed to be the same for all tags. We can fix this with some hacking a coffin tree. The following code has been tested with the development version of ggplot2 and may not work as it is written in the current version.

First, a simple reproducible example:

 p <- ggplot(mpg, aes(manufacturer, hwy)) + geom_boxplot() + coord_flip() + theme(axis.text.y = element_text(hjust = c(rep(1, 10), rep(0, 5)))) p # doesn't work 

enter image description here

The problem is that the width of the grob axis of the grob is set to the entire area of โ€‹โ€‹the plot. But we can manually enter and fix the width. Unfortunately, we have to fix this in several places:

 # get a vector of the y labels as strings ylabels <- as.character(unique(mpg$manufacturer)) library(grid) g <- ggplotGrob(p) # we need to fix the grob widths at various locations in the grob tree g$grobs[[3]]$children[[2]]$widths[1] <- max(stringWidth(ylabels)) g$grobs[[3]]$width <- sum(grobWidth(g$grobs[[3]]$children[[1]]), grobWidth(g$grobs[[3]]$children[[2]])) g$widths[3] <- g$grobs[[3]]$width # draw the plot grid.newpage() grid.draw(g) 

enter image description here

The ggplot2 axis drawing code can probably be changed to calculate the width, as I did here from the very beginning, and then the problem goes away.

+1
source

The method you use breaks into the main graphics engine, and the results may not always be obvious. See here for the answer that goes into the coffin tree and captures things.

However, for the problem outlined in the question, there is a simple solution that does not require any hacking. Just create labels that have some trailing spaces. I did it manually here, but you can also write a function that does this.

 ggplot(xx, aes(x = VALUE, y=CLONE, fill=YEAR)) + geom_bar(stat="identity", position="dodge") + scale_y_discrete(breaks = c("A", "B", "C", "D", "E"), labels = c("A ", "B ", "C", "D", "E ")) + facet_wrap(~TREAT) 

enter image description here

+1
source

All Articles