2

Here is a reproducible example:

I first create a function based on this example https://github.com/hadley/ggplot2/wiki/labeller then provide the data and a graph

label_wrap_gen <- function(width = 100) {
  function(variable, value) {
    lapply(strwrap(as.character(value), width=width, simplify=FALSE), 
           paste, collapse="\n")
  }
}

Data <- data.frame(Language=c("C++","C++","C++", "Java","Java","Java","Java", "PythonhasaREALLYWAYTOOlonglabel"), 
                Files=c(400, 210, 35,55,330,220,213,76), 
                Difficulty=c("a","b","c","d","e","f","g","h"), 
                stringsAsFactors=FALSE)

g <- ggplot(Data,aes(x=Difficulty,y=Files,fill=Difficulty))  #replaced fill=feetype,
h <- g + geom_bar(stat="identity",position="dodge") +   facet_grid(.~ Language, scales = "free_x", space="free",labeller=label_wrap_gen(width=.1)) 
h

which produces a ggplot graph with a label for "PythonhasaREALLYWAYTOOlonglabel" that will oftentimes run off the edge of the plot.

I've tried playing with the various geom_bar widths from the following link but too no avail: How to increase the space between the bars in a bar plot in ggplot2?

Any help here? Thanks so much.

Community
  • 1
  • 1
Luke Macaulay
  • 393
  • 5
  • 14
  • 1
    I know this isn't what you're looking for, but really, practically, you might want to think about using abbreviations and/or legends and defining those abbreviations elsewhere in the document. – N8TRO Jul 12 '13 at 04:58
  • Yeah, maybe that's the way to go on this... Thanks much. – Luke Macaulay Jul 12 '13 at 18:17

2 Answers2

4

If you break the "reallylonglabel with spaces it will behave as intended:

 "Python has a REALLY WAY TOO long label"  # will be handled correctly

OK. To your comment: here is a new labeller-function that will first split on any spaces (subject to low values of width) and then split on strings of length greater than 5.

label_wrap_gen2 <- function(width = 100) {
  function(variable, value) {
    inter <- lapply(strwrap(as.character(value), width=width, simplify=FALSE), 
           paste, collapse="\n")
    inter <- gsub("(.{5})", "\\1\n",inter)
  }
}

And if you supply less stringent arguments to "width" you can get this to accept width arguments in character-measured widths that are in the range of 5-10:

label_wrap_gen3 <- function(width = 100) {
  function(variable, value) {
    inter <- lapply(strwrap(as.character(value), width=width, simplify=FALSE), 
           paste, collapse="\n")
    inter <- gsub(paste0("(.{",width,"})"), "\\1\n",inter)
  }
}

# Seems to deliver expected results when called with:
  ... + facet_grid(..., labeller=label_wrap_gen3(width=5) )
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • I thought of that, but my real label is two longish words that even when split into two separate lines go off the edge of the margins. I guess I could use hyphens and such, but thought there would be a better way... Thanks for the suggestion. – Luke Macaulay Jul 12 '13 at 17:57
  • @Roger You would need to manually hyphenate; I could not find anything that would automatically wrap with automatic hyphenation (theoretically possible; TeX does it and `koRpus` has a function which figures out where a word can be hyphenated). Probably not worth the effort given the alternatives of abbreviating and manually doing it when necessary. All these solutions also suffer from the problem of picking the right width to wrap at which can change as the size of the plot changes (they don't automatically adapt to whatever size is available). – Brian Diggs Jul 12 '13 at 19:36
  • @BrianDiggs some effort has been made to pick the right size: http://stackoverflow.com/a/16735798/471093 – baptiste Jul 12 '13 at 19:53
  • @baptiste Thanks for that link; I hadn't seen that. – Brian Diggs Jul 12 '13 at 20:32
  • there are quite a few variations of this question out there, though it's the first time that people try to split _words_, AFAIK. – baptiste Jul 12 '13 at 20:37
  • Thanks baptiste and BrianDiggs. I ended up doing a manual hyphenation in the character of the variable which worked acceptably well. These additional functions by DWin get the words to wrap, but of course they're still difficult to read. I'm considering adding a couple of zero values on both sides of the "PythonhasaREALLYWAYTOOlonglabel" and renaming it to "PythonhasaREALLY- WAYTOOlonglabel" so that it can be read on only two lines and has additional space on the left and right. Will post the code now. – Luke Macaulay Jul 12 '13 at 21:26
0

While the answers so far are helpful in wrapping the text, the labels remain difficult to read. I've decided to go with adding a couple of zero values on both sides of the variable of interest and manually added a hyphenated name with a space for the factor of interest, changing "PythonhasaREALLYWAYTOOlonglabel" to "PythonhasaREALLY- WAYTOOlonglabel", which does what I'd like better so far. While it leaves perhaps too big of spaces on both sides of the "PythonhasaREALLY- WAYTOOlonglabel", it gives me the space I need.

Using the following code:

label_wrap_gen <- function(width = 100) {
  function(variable, value) {
    lapply(strwrap(as.character(value), width=width, simplify=FALSE), 
           paste, collapse="\n")
  }
}

Data <- data.frame(Language=c("C++","C++","C++", "Java","Java","Java","Java", "PythonhasaREALLY- WAYTOOlonglabel","PythonhasaREALLY- WAYTOOlonglabel","PythonhasaREALLY- WAYTOOlonglabel"), #note that I add a hyphen here and two placeholders that will have 0 values
                   Files=c(400, 210, 35,55,330,220,213,0,76,0), #note that I add two 0 values here
                   Difficulty=c("a","b","c","d","e","f","g","h","i","j"), 
                   stringsAsFactors=FALSE)

Data
g <- ggplot(Data,aes(x=Difficulty,y=Files,fill=Difficulty))  #replaced fill=feetype,
h <- g + geom_bar(stat="identity",position="dodge") +   facet_grid(.~ Language, scales = "free_x", space="free",labeller=label_wrap_gen(width=.1)) 

There is probably a way to make the spaces on either side a bit narrower, but I'm not sure how to do that yet...

Luke Macaulay
  • 393
  • 5
  • 14