Search code examples
rtextplotword-wrap

R: Wrap a long text so that each line has the same length


I am trying to add a long text to a plot. The goal is to wrap the text so that each line is equal in length. I looked through several functions: strwrap, format, text. But none of these seem to have an option for making the lines equal.

I imagine the solution should adding spaces between words in shorter lines to make up for missing characters. Maybe there is a function/argument that I missed?

Below is my current wrapping (without equal lengths):

txt <- paste(sample(LETTERS, 1000, replace=TRUE), collapse="")
txt <- strsplit(txt, "A|I|O|E|U")
txt <- paste(txt[[1]], collapse=" ")

plot(NA, xlim=c(0,1), ylim=c(0,1))
text(0.0, 0.5, paste(strwrap(txt, width=50), collapse="\n"), pos=4, cex=0.7)

textplot


Solution

  • Here is a one hack to achieve it.

    1) Define a function that expands a string to desired length by adding spaces between words.

    expandWidth <- function(str, width) {
      nmiss <- max(0, width-nchar(str))
      words <- unlist(strsplit(str, " "))
      ngaps <- length(words)-1
      addToAll   <- nmiss %/% ngaps
      addToStart <- nmiss %% ngaps
      nSpaces    <- rep(addToAll, ngaps)
      nSpaces[0:addToStart] <- nSpaces[0:addToStart] + 1
      spaces <- sapply(Map(rep, " ", nSpaces+1), paste, collapse="")
      paste(apply(rbind(c("", spaces), words), 2, paste, collapse=""), collapse="")
    }
    

    2) Deal with text.

    txt <- paste(sample(LETTERS, 1000, replace=TRUE), collapse="")
    txt <- strsplit(txt, "A|I|O|E|U")
    txt <- paste(txt[[1]], collapse=" ")
    
    # Add spaces
    txt <- sapply(strwrap(txt, width=50), expandWidth, 50)
    

    3) Use font with equal character sizes ( as noted by @rawr )

    plot(NA, xlim=c(0,1), ylim=c(0,1))
    text(0.0, 0.5, paste(txt, collapse="\n"), pos=4, cex=0.7, family="mono")
    

    Result:

    resultPic