[R] Newey West and Singular Matrix
Achim Zeileis
Achim.Zeileis at uibk.ac.at
Thu Sep 23 01:41:15 CEST 2010
On Wed, 22 Sep 2010, ivo welch wrote:
> dear R experts: I am writing my own little newey-west standard error
> function, with heteroskedasticity and arbitrary x period
> autocorrelation corrections. including my function in this post here
> may help others searching for something similar. it is working quite
> well, except on occasion, it complains that
>
> Error in solve.default(crossprod(x.na.omitted, x.na.omitted)) :
> system is computationally singular: reciprocal condition number =
> 3.63797e-23
>
> I know that lm can do the inversion, so I presume that there is a more
> stable way than qr.solve . I looked into lm, then into lm.fit, and it
> seems to invoke dqrls . is this the recommended way, or is there a
> higher-level more stable matrix inversion routine that I could use?
I typically leverage chol2inv(). In "strucchange" I've written a small
convenience function solveCrossprod() that provides two different
approaches (plus the naive method). The man page has a few comments. The
function defintions are all one-liners, though.
> help is, as always, appreciated. (also, if you see something else
> silly in my code, let me know, please.)
1. There is no assert() function in base R.
2. The error message of se.neweywest() refers to se.white.
3. A much more flexible and powerful solution of this is included
in package "sandwich", see the vignette for details. The code
sqrt(diag(NeweyWest(lm_object, lag = 0, prewhite = 0)))
replicates se.neweywest(lm_object) but has the following advantages:
it also does automatic bandwidth selection, it does not require setting
"x = TRUE", it incorporates other kernel weighting functions, supports
prewhitening etc.
Best,
Z
> regards,
>
> /iaw
>
>
> se.neweywest <- function( lmobject.withxtrue, ar.terms =0 ) {
> assert( (class(lmobject.withxtrue)=="lm"),
> "[se.white] works only on 'lm' objects, not on ",
> class(lmobject.withxtrue), "objects \n" )
> x.na.omitted <- lmobject.withxtrue$x
> assert( class(x.na.omitted)=="matrix", "[se.white] internal
> error---have no X matrix. did you invoke with 'x=TRUE'?\n")
> r.na.omitted <- residuals( lmobject.withxtrue )
>
> diagband.matrix <- function( m, ar.terms ) {
> nomit <- m-ar.terms-1
> mm <- matrix( TRUE, nrow=m, ncol=m )
> mm[1:nomit,(ncol(mm)-nomit+1):ncol(mm)] <- (lower.tri(
> matrix(TRUE, nrow=nomit, ncol=nomit) ))
> mm[(ncol(mm)-nomit+1):ncol(mm),1:nomit] <- (upper.tri(
> matrix(TRUE, nrow=nomit, ncol=nomit) ))
> mm
> }
>
> ## V(b) = inv(X'X) X' diag(e^2) X inv(X'X)
> invx <- qr.solve( crossprod( x.na.omitted, x.na.omitted ) )
> if (!ar.terms) resid.matrix <- diag( r.na.omitted^2 ) else {
> full <- r.na.omitted %*% t(r.na.omitted)
>
> ## the following is not particularly good. see, we could zero out also
> ## items which are multiplications with a missing residual for example,
> ## if we do an ar1 correction, and obs 5 is missing, then the AR term on
> ## 4 and 6 could be set to 0. right now, we just adjust for an add'l
> ## term.
>
> maskmatrix <- diagband.matrix( length(r.na.omitted), ar.terms )
> resid.matrix <- full * maskmatrix
> }
>
> invx.x <- invx %*% t(x.na.omitted)
> vmat <- invx.x %*% resid.matrix %*% t(invx.x)
> sqrt(diag(vmat))
> }
>
> ______________________________________________
> R-help at 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.
>
More information about the R-help
mailing list