2
votes

I am making a ggplot. The x-axis are factors, and the labels are long.

I can't shorten the labels, they're as short as they can be.

I am interested to make it so that labels are vertically offset. My preference would be to have every odd label at height 0, and every even at height 2 units more distant from the x-axis.

I have looked here, ggplot-hopeful-help, but have real trouble interpreting what is going on, and so can't make a useful version of this.

Any ideas??

(example code below... I'm not very good at formatting code here, it appears... sry.)

library("ggplot2"); 
stack <- data.frame(value =rnorm(n = 1000, sd = 2, mean=34)); stack$fact <- as.factor(rep(1:5, each=1000/5));
ggplot(stack, aes(x=fact, y=value)) + geom_boxplot(aes(fill=fact))+ scale_x_discrete(breaks=c("1", "2", "3", "4", "5"), labels=c("hi","don't suggest I shorten the text","I need long labels", "This is a long factor label","This label is very long"))
2
The answer you are referening to, gives you solution you are looking for. For your case it would be + theme(axis.text.x = element_text(vjust = grid::unit(c(-2, 0), "points"))) where -2 will be for the odd labels and 0 for the even labels.Didzis Elferts

2 Answers

8
votes

Understand it or not, it seems to work pretty well. Calling the plot in your question your_plot:

your_plot + theme(axis.text.x = element_text(vjust = grid::unit(c(-2, 0, 2), "points")))

enter image description here

Specifying preferences in theme() is the way to make adjustments to the trappings of your ggplot. axis.text.x is modifying only the x-axis text, which is created with preferences set by element_text(). You could specify the font size, the font family, an angle for rotation, etc., in element_text(). vjust stands for "vertical justification", so setting the vjust to three values, -2, 0 and 2 is applying those values to successive x-axis labels. (Apparently the negative is up, which surprised me.)

Using grid::unit() allows us to specify the units (in this case points) by which the text is vertically moved. Looking at ?grid::units reveals that you could use inches, cm, or several other units.

The only problem is the overlap with the x axis title. I think the easiest way to fix this is to add a couple linebreaks "\n" before it:

your_plot + 
    theme(axis.text.x = element_text(vjust = grid::unit(c(-2, 0, 2), "points"))) +
    labs(x = "\n\nfact")

enter image description here

Another solution would be to rotate the text:

your_plot + theme(axis.text.x = element_text(angle = -90, hjust = 0, vjust = 0))

enter image description here

For more reading, there's a whole vignette on ggplot2 theming.

0
votes
stack <- data.frame(value =rnorm(n = 1000, sd = 2, mean=34))
stack$fact <- as.factor(rep(1:5, each=1000/5))

ggplot(stack, aes(x=fact, y=value)) + 
geom_boxplot(aes(fill=fact)) + 
scale_x_discrete(breaks=c("1", "2", "3", "4", "5"), labels=c("hi","don't suggest I shorten the text","I need long labels", "This is a long factor label","This label is very long"))+
theme(axis.text.x = element_text(vjust = grid::unit(c(0, 2), "points"))) + 
theme(axis.title.x = element_text(vjust = -0.6))

Actually the solution discussed in the link you reported required only slight modification. I also added

theme(axis.title.x = element_text(vjust = -0.6)) 

to lower x-axis label to prevent overlapping.