On 2/9/2012 6:24 PM, ilai wrote:
You do not provide mlm.influence() so your code can't be reproduced.
Or did you mean to put lm.influence() in the formals to your hatvalues.mlm ?
If yes, then 1) you have a typo 2) lm.influence doesn't allow you to
pass on arguments, maybe try influence.lm instead.
No, I've written an S3 method, influence.mlm and a computational method,
mlm.influence, both of which take an m= argument. I didn't post all the
code because I thought the question might have an easy answer based on
what I provided.
I include all the code and a test case in the attached .txt file that
can be sourced.
-Michael
Elai
On Thu, Feb 9, 2012 at 1:42 PM, Michael Friendly<frien...@yorku.ca> wrote:
I'm trying to write some functions extending influence measures to
multivariate linear models and also
allow subsets of size m>=1 to be considered for deletion diagnostics. I'd
like these to work roughly parallel
to those functions for the univariate lm where only single case deletion
(m=1) diagnostics are considered.
Corresponding to stats::hatvalues.lm, the S3 method for class "lm" objects,
hatvalues<-function (model, ...)
UseMethod("hatvalues")
hatvalues.lm<-
function (model, infl = lm.influence(model, do.coef = FALSE), ...)
{
hat<- infl$hat
names(hat)<- names(infl$wt.res)
hat
}
I have, for class "mlm" objects
hatvalues.mlm<- function(model, m=1, infl=mlm.influence(model, m=m, do.coef
= FALSE), ...)
{
hat<- infl$H
m<- infl$m
names(hat)<- if(m==1) infl$subsets else apply(infl$subsets,1, paste,
collapse=',')
hat
}
where mlm.influence() does the calculations, but also allows the m= argument
to specify subset size.
Yet when I test this I can't seem to pass the m= argument directly, so that
it gets stuffed in to the infl=
call to mlm.influence.
# fit an mlm
library(heplots)
Rohwer2<- subset(Rohwer, subset=group==2)
rownames(Rohwer2)<- 1:nrow(Rohwer2)
Rohwer.mod<- lm(cbind(SAT, PPVT, Raven) ~ n+s+ns+na+ss, data=Rohwer2)
class(Rohwer.mod)
[1] "mlm" "lm"
## this doesn't work, as I would like it to, calling the hatvalues.mlm
method, but passing m=2:
hatvalues(Rohwer.mod, m=2)
Error in UseMethod("hatvalues") :
no applicable method for 'hatvalues' applied to an object of class
"c('double', 'numeric')"
I don't understand why this doesn't just call hatvalues.mlm, since
Rohwer.mod is of class "mlm".
# These work -- calling hatvalues.mlm explicitly, or passing the infl=
argument with the call to
# mlm.influence
hatvalues.mlm(Rohwer.mod, m=2)
hatvalues(Rohwer.mod, infl=mlm.influence(Rohwer.mod,m=2))
Can someone help me understand what is wrong and how to make the .mlm method
allow m= to be passed
directly to the infl= computation?
thx,
-Michael
--
Michael Friendly Email: friendly AT yorku DOT ca
Professor, Psychology Dept.
York University Voice: 416 736-5115 x66249 Fax: 416 736-5814
4700 Keele Street Web: http://www.datavis.ca
Toronto, ONT M3J 1P3 CANADA
______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Michael Friendly Email: friendly AT yorku DOT ca
Professor, Psychology Dept.
York University Voice: 416 736-5115 x66249 Fax: 416 736-5814
4700 Keele Street Web: http://www.datavis.ca
Toronto, ONT M3J 1P3 CANADA
# S3 method for class "mlm"
influence.mlm <- function(model, m=1, do.coef=TRUE, ...)
mlm.influence(model, m=m, do.coef = do.coef, ...)
# main computation a la lm.influence
mlm.influence <-
function (model, m=1, do.coef = TRUE, ...)
{
# helper functions
vec <- function(M) {
R <- matrix(M, ncol=1)
if (is.vector(M)) return(R)
nn<-expand.grid(dimnames(M))[,2:1]
rownames(R) <- apply(as.matrix(nn), 1, paste, collapse=":")
R
}
X <- model.matrix(model)
data <- model.frame(model)
Y <- as.matrix(model.response(data))
r <- ncol(Y)
n <- nrow(X)
p <- ncol(X)
labels <- rownames(X)
call <- model$call
B <- coef(model)
E <- residuals(model)
XPXI <- solve(crossprod(X))
EPEI <- solve(crossprod(E))
vB <- vec(t(B))
S <- crossprod(E)/(n-p);
V <- solve(p*S) %x% crossprod(X)
subsets <- t(combn(n, m))
nsub <- nrow(subsets)
Beta <- as.list(rep(0, nsub))
R <- L <- H <- Q <- as.list(rep(0, nsub))
CookD <- as.vector(rep(0, nsub))
# FIXME: naive, direct computations can use qr() or update()
for (i in seq(nsub)) {
I <- c(subsets[i,])
rows <- which(!(1:n) %in% I)
XI <- X[rows,]
YI <- Y[rows,]
BI <- solve(crossprod(XI)) %*% t(XI) %*% YI
EI <- (Y - X %*% BI)[I, , drop=FALSE]
CookD[i] <- t(vec(B - BI)) %*% V %*% vec(B - BI)
H[[i]] <- X[I, , drop=FALSE] %*% XPXI %*% t(X[I, , drop=FALSE])
Q[[i]] <- EI %*% EPEI %*% t(EI)
if (do.coef) Beta[[i]] <- BI
L[[i]] <- if(m==1) H[[i]] / (1-H[[i]]) else H[[i]] %*%
solve(diag(m) - H[[i]])
R[[i]] <- if(m==1) Q[[i]] / (1-H[[i]])
else {
IH <- mpower(diag(m)-H[[i]], -1/2)
IH %*% Q[[i]] %*% IH
}
}
if(m==1) {
H <- unlist(H)
Q <- unlist(Q)
L <- unlist(L)
R <- unlist(R)
subsets <- c(subsets)
}
result <- list(m=m, H=H, Q=Q, CookD=CookD, L=L, R=R, subsets=subsets,
labels=labels, call=call)
if (do.coef) result <- c(result, list(Beta=Beta))
class(result) <-"inflmlm"
result
}
#####################
# extractor functions -- trying to find a way to be consistent with the .lm
versions
hatvalues.mlm <- function(model, m=1, infl=mlm.influence(model, m=m, do.coef =
FALSE), ...)
{
hat <- infl$H
m <- infl$m
names(hat) <- if(m==1) infl$subsets else apply(infl$subsets,1, paste,
collapse=',')
hat
}
cooks.distance.mlm <-
function (model, infl = mlm.influence(model, do.coef = FALSE), ...)
{
cookd <- infl$CookD
m <- infl$m
names(cookd) <- if(m==1) infl$subsets else apply(infl$subsets,1, paste,
collapse=',')
cookd
}
TESTME <- TRUE
if(TESTME) {
library(heplots)
Rohwer2 <- subset(Rohwer, subset=group==2)
rownames(Rohwer2)<- 1:nrow(Rohwer2)
Rohwer.mod <- lm(cbind(SAT, PPVT, Raven) ~ n+s+ns+na+ss, data=Rohwer2)
## this doesn't work, as I would like it to, calling the hatvalues.mlm method,
but passing m=2:
hatvalues(Rohwer.mod, m=2)
## Error in UseMethod("hatvalues") :
## no applicable method for 'hatvalues' applied to an object of class
"c('double', 'numeric')"
#I don't understand why this doesn't just call hatvalues.mlm, since Rohwer.mod
is of class "mlm".
# These work -- calling hatvalues.mlm explicitly, or passing the infl= argument
with the call to
# mlm.influence
hatvalues.mlm(Rohwer.mod, m=2)
hatvalues(Rohwer.mod, infl=mlm.influence(Rohwer.mod,m=2))
}
______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.