9

I would like to create a simple bar chart with ggplot2 and my problem is that my x variable contains long strings so the labels are overlaid.

Here are fake datas and the plot :

library(dplyr)
library(tidyr)
library(ggplot2)

set.seed(42)
datas <- data.frame(label = sprintf("aLongLabel%d", 1:8), 
           ok = sample(seq(0, 1, by = 0.1), 8, rep = TRUE)) %>% 
  mutate(err = abs(ok - 1)) %>% 
  gather(type, freq, ok, err)

datas %>% 
  ggplot(aes(x = label, y = freq)) + 
  geom_bar(aes(fill = type), stat = "identity")

enter image description here

I would like to replace the labels by shorter ones and create a legend to show the matches.

What I've tried :

I use the shape aes parameter in geo_point which will create a legend with shapes (and plots shapes that I hide with alpha = 0). Then I change the shapes with scale_shape_manual and replace the x labels with scale_x_discrete. With guides I override the alpha parameter of my shapes so they wont be invisible in the legend.

leg.txt <- levels(datas$label)
x.labels <- structure(LETTERS[seq_along(leg.txt)], 
                      .Names = leg.txt)

datas %>% 
  ggplot(aes(x = label, y = freq)) + 
  geom_bar(aes(fill = type), stat = "identity") + 
  geom_point(aes(shape = label), alpha = 0) + 
  scale_shape_manual(name = "Labels", values = x.labels) + 
  guides(shape = guide_legend(override.aes = list(size = 5, alpha = 1))) + 
  scale_x_discrete(name = "Label", labels = x.labels)

enter image description here

It gives me the expected output but I feel like this is very hacky.

Does ggplot2 provides a way to do this more directly ? Thanks.

Julien Navarre
  • 6,787
  • 2
  • 33
  • 65
  • 1
    You should rotate them instead: http://stackoverflow.com/questions/1330989/rotating-and-spacing-axis-labels-in-ggplot2 –  Jun 03 '15 at 07:59
  • I didn't even think about that... It could be a good idea indeed. – Julien Navarre Jun 03 '15 at 08:04
  • 2
    I like this a lot, but it needs a better title so people can find it. Maybe something like "Shortening ggplot labels with abbreviations". And while rotation is a good solution, sometimes this would be better. – Mike Wise Jun 03 '15 at 08:05
  • I suggest Pascal (or you) should post an answer and image with rotated labels, mark that as correct, and then leave this here. I think it is a valuable and useful example even if rotated titles are usually the right solution. – Mike Wise Jun 03 '15 at 08:39
  • Thanks for your advices, my english is not that good and I really struggling to find appropriate titles. I will add the Pascal's solution in my post. – Julien Navarre Jun 03 '15 at 08:45
  • 1
    If I may suggest, an angle between 30 and 45 degrees will look better. –  Jun 03 '15 at 09:12
  • 1
    Post it as a solution to your own problem then and mark it as correct. Makes more sense than posting it in the question. – Mike Wise Jun 03 '15 at 09:15
  • 1
    Also it will stay as an open unanswered question is you leave it like this which annoys the moderators and caretakers. – Mike Wise Jun 03 '15 at 09:20

1 Answers1

2

Rotation solution suggested by Pascal

Rotate the labels and align them to the edge :

datas %>% 
  ggplot(aes(x = label, y = freq)) + 
  geom_bar(aes(fill = type), stat = "identity") + 
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

enter image description here

Mike Wise
  • 18,767
  • 6
  • 71
  • 95
Julien Navarre
  • 6,787
  • 2
  • 33
  • 65