G'day Brian,

>>>>> "BDR" == Prof Brian Ripley <[EMAIL PROTECTED]> writes:

    BDR> The proposed fix regretably will not work, since one can do
    BDR> things like

    BDR> library(MASS)
    BDR> prcomp(~ dist + dist:climb, hills)
Yes, I had the impression that this would work with the current
version but dismissed it as unintentional. ;-)

I wouldn't expect anyone to specify interaction terms in a principal
components analysis, but perhaps there are valid reasons to do so.

Attached is a slightly modified patch which still allows the above
example but also the changes that I proposed.  On my machine, R-devel
with this patch passes "make check FORCE=FORCE" and produces the
following output:

      > library(DAAG)
      > res <- prcomp(~ . - case - site - Pop - sex, possum)
      > res <- princomp(~ . - case - site - Pop - sex, possum)
      > res <- prcomp(~ . - case - site - Pop, possum)
      Error in prcomp.formula(~. - case - site - Pop, possum) : 
        PCA applies only to numerical variables
      > res <- princomp(~ . - case - site - Pop, possum)
      Error in princomp.formula(~. - case - site - Pop, possum) : 
        PCA applies only to numerical variables
      > library(MASS)
      
      Attaching package: 'MASS'
      
      
        The following object(s) are masked from package:DAAG :
      
         hills 
      
      > prcomp(~ dist + dist:climb, hills)
      Standard deviations:
      [1] 29655.128279     3.101566
      
      Rotation:
                          PC1          PC2
      dist       -0.000154139 -0.999999988
      dist:climb -0.999999988  0.000154139

Cheers,

        Berwin

Index: src/library/stats/R/princomp.R
===================================================================
--- src/library/stats/R/princomp.R      (revision 37574)
+++ src/library/stats/R/princomp.R      (working copy)
@@ -10,13 +10,15 @@
     mf$... <- NULL
     mf[[1]] <- as.name("model.frame")
     mf <- eval.parent(mf)
+    na.act <- attr(mf, "na.action")
+    mt <- attr(mf, "terms") # allow model.frame to update it
+    attr(mt, "intercept") <- 0
+    mterms <- attr(mt, "factors")
+    mterms <- rownames(mterms)[apply(mterms, 1, any)]
     ## this is not a `standard' model-fitting function,
     ## so no need to consider contrasts or levels
-    if(any(sapply(mf, function(x) is.factor(x) || !is.numeric(x))))
+    if(any(sapply(mterms, function(x) is.factor(mf[,x]) || 
!is.numeric(mf[,x]))))
         stop("PCA applies only to numerical variables")
-    na.act <- attr(mf, "na.action")
-    mt <- attr(mf, "terms") # allow model.frame to update it
-    attr(mt, "intercept") <- 0
     x <- model.matrix(mt, mf)
     res <- princomp.default(x, ...)
     ## fix up call to refer to the generic, but leave arg name as `formula'
Index: src/library/stats/R/prcomp.R
===================================================================
--- src/library/stats/R/prcomp.R        (revision 37574)
+++ src/library/stats/R/prcomp.R        (working copy)
@@ -37,13 +37,15 @@
     mf$... <- NULL
     mf[[1]] <- as.name("model.frame")
     mf <- eval.parent(mf)
+    na.act <- attr(mf, "na.action")
+    mt <- attr(mf, "terms")
+    attr(mt, "intercept") <- 0
+    mterms <- attr(mt, "factors")
+    mterms <- rownames(mterms)[apply(mterms, 1, any)]
     ## this is not a `standard' model-fitting function,
     ## so no need to consider contrasts or levels
-    if (any(sapply(mf, function(x) is.factor(x) || !is.numeric(x))))
+    if (any(sapply(mterms, function(x) is.factor(mf[,x]) || 
!is.numeric(mf[,x]))))
         stop("PCA applies only to numerical variables")
-    na.act <- attr(mf, "na.action")
-    mt <- attr(mf, "terms")
-    attr(mt, "intercept") <- 0
     x <- model.matrix(mt, mf)
     res <- prcomp.default(x, ...)
     ## fix up call to refer to the generic, but leave arg name as `formula'
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to