[R] abbreviate or wrap dimname labels
Michael Friendly
friendly at yorku.ca
Sat Apr 16 00:00:06 CEST 2005
What a lovely example of recursion, function mapping, and
vectorization! Thanks, John.
-Michael
John Fox wrote:
> Dear Mark and Mike,
>
> I had a chance to speak with Mike this afternoon, and he explained to me, so
> politely that I almost missed it, that I hadn't read his posting very
> carefully. Sorry for that.
>
> Anyway, here's an alternative solution, which I think will meet Mike's
> needs:
>
> abbrev <- function(text, width=10, split=" "){
> if (is.list(text)) return(lapply(text, abbrev, width=width,
> split=split))
> if (length(text) > 1)
> return(as.vector(sapply(text, abbrev, width=width, split=split)))
> words <- strsplit(text, split=split)[[1]]
> words <- ifelse(nchar(words) <= width, words,
> abbreviate(words, minlength=width))
> words <- paste(words, collapse=" ")
> paste(strwrap(words, width=width), collapse="\n")
> }
>
>
>>abbrev(lab) # Mike's example
>
> $OccFather
> [1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual" "Lower\nmanual"
>
> [5] "Farm"
>
> $OccSon
> [1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual" "Lower\nmanual"
>
> [5] "Farm"
>
>
>>abbrev(labels) # Mark's example
>
> [1] "This is\na long\nlabel 1" "This is\na long\nlabel 2"
> [3] "This is\na long\nlabel 3" "This is\na long\nlabel 4"
> [5] "This is\na long\nlabel 5" "This is\na long\nlabel 6"
> [7] "This is\na long\nlabel 7" "This is\na long\nlabel 8"
> [9] "This is\na long\nlabel 9" "This is\na long\nlabel 10"
>
>
> I hope that this is more helpful than my original response.
>
> John
>
> --------------------------------
> John Fox
> Department of Sociology
> McMaster University
> Hamilton, Ontario
> Canada L8S 4M4
> 905-525-9140x23604
> http://socserv.mcmaster.ca/jfox
> --------------------------------
>
>
>>-----Original Message-----
>>From: r-help-bounces at stat.math.ethz.ch
>>[mailto:r-help-bounces at stat.math.ethz.ch] On Behalf Of Marc Schwartz
>>Sent: Friday, April 15, 2005 12:30 PM
>>To: Michael Friendly
>>Cc: R-Help
>>Subject: Re: [R] abbreviate or wrap dimname labels
>>
>>On Fri, 2005-04-15 at 12:12 -0400, Michael Friendly wrote:
>>
>>>For a variety of displays (mosaicplots, barplots, ...) one
>>
>>often wants
>>
>>>to either abbreviate or wrap long labels, particularly when
>>
>>these are
>>
>>>made up of several words.
>>>In general, it would be nice to have a function,
>>>
>>>abbreviate.or.wrap <-
>>> function(x, maxlength=10, maxlines=2, split=" ") { }
>>>
>>>that would take a character vector or a list of vectors, x,
>>
>>and try to
>>
>>>abbreviate or wrap them to fit approximately the maxlength and
>>>maxlines constraints, using the split argument to specify allowable
>>>characters to wrap to multiple lines.
>>>
>>>For example, this two-way table has dimnames too long to be
>>
>>displayed
>>
>>>nicely in a mosaicplot:
>>>
>>> > library(catspec)
>>> > library(vcd)
>>> >
>>> > data(FHtab)
>>> > FHtab<-as.data.frame(FHtab)
>>> >
>>> > xtable <- xtabs(Freq ~ .,FHtab)
>>> > lab <- dimnames(xtable)
>>> > lab
>>>$OccFather
>>>[1] "Upper nonmanual" "Lower nonmanual" "Upper manual"
>>
>>"Lower manual"
>>
>>>[5] "Farm"
>>>
>>>$OccSon
>>>[1] "Upper nonmanual" "Lower nonmanual" "Upper manual"
>>
>>"Lower manual"
>>
>>>[5] "Farm"
>>>
>>>abbreviate works here, but gives results that aren't very readable:
>>>
>>> > lapply(lab, abbreviate, 8)
>>>$OccFather
>>>Upper nonmanual Lower nonmanual Upper manual Lower
>>
>>manual Farm
>>
>>> "Upprnnmn" "Lwrnnmnl" "Uppermnl" "Lowermnl"
>>> "Farm"
>>>
>>>$OccSon
>>>Upper nonmanual Lower nonmanual Upper manual Lower manual
>>> Farm
>>> "Upprnnmn" "Lwrnnmnl" "Uppermnl" "Lowermnl"
>>> "Farm"
>>>
>>>In a related thread, Marc Schwartz proposed a solution for wrapping
>>>labels, based on
>>>
>>> >short.labels <- sapply(labels, function(x) paste(strwrap(x,
>>> 10), collapse = "\n"), USE.NAMES = FALSE)
>>>
>>>But, my attempt to use strwrap in my context gives a single
>>
>>string for
>>
>>>each set of dimension names:
>>>
>>> > stack.lab <-function(x) { paste(strwrap(x,10), collapse
>>
>>= "\n") }
>>
>>>>lapply(lab, stack.lab) $OccFather [1]
>>>
>>"Upper\nnonmanual\nLower\nnonmanual\nUpper\nmanual\nLower\nman
>>ual\nFarm"
>>
>>>$OccSon
>>>[1]
>>
>>"Upper\nnonmanual\nLower\nnonmanual\nUpper\nmanual\nLower\nman
>>ual\nFarm"
>>
>>>For my particular example, I can do what I want with gsub,
>>
>>but it is
>>
>>>hardly general:
>>>
>>> > lab[[1]] <- gsub(" ","\n", lab[[1]])
>>> > lab[[2]] <- lab[[1]] # cheating: I know it's a square table
>>> > lab
>>>$OccFather
>>>[1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual"
>>>"Lower\nmanual"
>>>[5] "Farm"
>>>
>>>$OccSon
>>>[1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual"
>>>"Lower\nmanual"
>>>[5] "Farm"
>>>
>>> > dimnames(xtable) <- lab
>>>
>>>Then,
>>>mosaicplot(xtable, shade=TRUE)
>>>gives a nice display!
>>>
>>>Can anyone help with a more general solution for wrapping labels or
>>>abbreviate.or.wrap()?
>>>
>>>thanks,
>>>-Michael
>>
>>
>>Michael,
>>
>>This is not completely generic (I have not used abbreviate()
>>here) and it could take some further fine tuning and perhaps
>>even consideration of creating a generic method. However, a
>>possible solution to the problem of using my previous
>>approach on a list object and giving some flexibility to also
>>handle vectors:
>>
>>
>># Core wrapping function
>>wrap.it <- function(x, len)
>>{
>> sapply(x, function(y) paste(strwrap(y, len),
>> collapse = "\n"),
>> USE.NAMES = FALSE)
>>}
>>
>>
>># Call this function with a list or vector
>>wrap.labels <- function(x, len)
>>{
>> if (is.list(x))
>> {
>> lapply(x, wrap.it, len)
>> } else {
>> wrap.it(x, len)
>> }
>>}
>>
>>
>>
>>Thus, for your labels in a list:
>>
>>
>>>wrap.labels(lab, 10)
>>
>>$OccFather
>>[1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual"
>>[4] "Lower\nmanual" "Farm"
>>
>>$OccSon
>>[1] "Upper\nnonmanual" "Lower\nnonmanual" "Upper\nmanual"
>>[4] "Lower\nmanual" "Farm"
>>
>>
>>and for the example vector in my prior post:
>>
>>
>>>labels <- factor(paste("This is a long label ", 1:10))
>>>wrap.labels(labels, 10)
>>
>> [1] "This is\na long\nlabel 1" "This is\na long\nlabel 2"
>> [3] "This is\na long\nlabel 3" "This is\na long\nlabel 4"
>> [5] "This is\na long\nlabel 5" "This is\na long\nlabel 6"
>> [7] "This is\na long\nlabel 7" "This is\na long\nlabel 8"
>> [9] "This is\na long\nlabel 9" "This is\na long\nlabel 10"
>>
>>
>>To incorporate abbreviate() here, you could perhaps modify the
>>wrap.labels() syntax to use a "wrap = TRUE/FALSE" argument to
>>explicitly
>>indicate which approach you want, or perhaps develop some
>>decision tree
>>approach to automate the process.
>>
>>HTH,
>>
>>Marc Schwartz
>>
>>______________________________________________
>>R-help at stat.math.ethz.ch mailing list
>>https://stat.ethz.ch/mailman/listinfo/r-help
>>PLEASE do read the posting guide!
>>http://www.R-project.org/posting-guide.html
--
Michael Friendly Email: friendly at yorku.ca
Professor, Psychology Dept.
York University Voice: 416 736-5115 x66249 Fax: 416 736-5814
4700 Keele Street http://www.math.yorku.ca/SCS/friendly.html
Toronto, ONT M3J 1P3 CANADA
More information about the R-help
mailing list