[R] poor man's scree plot for SVD: multiline labels and total lines

Michael Friendly friendly at yorku.ca
Fri Feb 6 22:47:10 CET 2015


In the ca package, the summary method gives the following output, as a 
"poor man's scree plot",
showing eigenvalues, their percents, and a character-based scree plot:

# install.packages("ca")
haireye <- margin.table(HairEyeColor, 1:2)
library(ca)
haireye.ca <- ca(haireye)

summary(haireye.ca, rows=FALSE, columns=FALSE)

Principal inertias (eigenvalues):

  dim    value      %   cum%   scree plot
  1      0.208773  89.4  89.4  **********************
  2      0.022227   9.5  98.9  **
  3      0.002598   1.1 100.0
         -------- -----
  Total: 0.233598 100.0

I'd like to enhance this, to something like the following, using 
multiline column labels and also showing the totals,
but the code in ca::print.summary.ca is too obtuse to try to reuse or 
modify.

Singular values and Principal inertias (eigenvalues)

   Singular  Principal  Percents   Cum  Scree plot
   values    inertias

1 0.456916  0.208773     89.4    89.4 ******************************
2 0.149086  0.022227      9.5    98.9 ***
3 0.050975  0.002598      1.1   100.0
             --------     ----
             0.233598    100.0

I made a start, defining a scree.ca function, and an associated print 
method, but I can't figure out how to
print multiline labels and the totals for relevant columns.  Can someone 
help?

Here are my functions:

scree.ca <- function (obj, scree.width=30) {
     values <- obj$sv
     inertia <- values^2
     pct <- 100*inertia/sum(inertia)
     scree <- character(length(pct))
     stars <- round(scree.width * pct / max(pct), 0)
     for (q in 1:length(pct)) {
       s1 <- paste(rep("*", stars[q]), collapse = "")
       s2 <- paste(rep(" ", scree.width - stars[q]), collapse = "")
       scree[q] <- paste(" ", s1, s2, sep = "")
       }
     dat <- data.frame(values, inertia, pct=round(pct,1), 
Cum=round(cumsum(pct),1), scree, stringsAsFactors=FALSE)
     heading <- "Singular values and Principal inertias (eigenvalues)"
     attr(dat,"heading") <- heading
     attr(dat$values, "label") <- "Singular\nvalues"
     attr(dat$inertia, "label") <- "Principal\ninertias"
     attr(dat$pct, "label") <- "Percents"
     class(dat) <- c("scree.ca", "data.frame")
     dat
}

print.scree.ca <- function(x, digits=5, ...) {
   if (!is.null(heading <- attr(x, "heading")))
     {cat(heading, sep = "\n"); cat("\n")}
     print.data.frame(x, digits=digits, ...)
}

And, a test use:

 > sc <- scree.ca(haireye.ca)
 > str(sc)
Classes ‘scree.ca’ and 'data.frame':    3 obs. of  5 variables:
  $ values : atomic  0.457 0.149 0.051
   ..- attr(*, "label")= chr "Singular\nvalues"
  $ inertia: atomic  0.2088 0.0222 0.0026
   ..- attr(*, "label")= chr "Principal\ninertias"
  $ pct    : atomic  89.4 9.5 1.1
   ..- attr(*, "label")= chr "Percents"
  $ Cum    : num  89.4 98.9 100
  $ scree  : chr  " ******************************" " 
***                           " "                               "
  - attr(*, "heading")= chr "Singular values and Principal inertias 
(eigenvalues)"
 > sc
Singular values and Principal inertias (eigenvalues)

     values   inertia  pct   Cum                           scree
1 0.456916 0.2087727 89.4  89.4  ******************************
2 0.149086 0.0222266  9.5  98.9  ***
3 0.050975 0.0025984  1.1 100.0
 >


-- 
Michael Friendly     Email: friendly AT yorku DOT ca
Professor, Psychology Dept. & Chair, Quantitative Methods
York University      Voice: 416 736-2100 x66249 Fax: 416 736-5814
4700 Keele Street    Web:http://www.datavis.ca
Toronto, ONT  M3J 1P3 CANADA



More information about the R-help mailing list