####################################################### #### R code for computing the Biweight Correlation #### #### J. Hardin, A. Mitani, L. Hicks, B. VanKoten #### #### last updated 6/05/2007 #### ####################################################### ################# ## EXAMPLE ## ################# library(rrcov) library(MASS) samp.data <- mvrnorm(30,mu=c(0,0),Sigma=matrix(c(1,.75,.75,1),ncol=2)) # you need MASS r<-0.2 # breakdown n1<-30 # number of samples c1<-rejpt.bw(p=2,r)[1] b0<-erho.bw(p=2,c1)[1] samp.mcd <- covMcd(samp.data) #you need rrcov samp.bw <- biwt.est(samp.data,n1,p=2,r,c1,b0,samp.mcd) samp.bw.corr <- samp.bw$biwt.sig[1,2] / sqrt(samp.bw$biwt.sig[1,1]*samp.bw$biwt.sig[2,2]) ############## # to speed up the calculations, use the median/mad for the initialization: ############## samp.init <- list() samp.init$cov <- diag(apply(samp.data,2,mad,na.rm=T)) samp.init$center <- apply(samp.data,2,median,na.rm=T) samp.bw <- biwt.est(samp.data,n1,p=2,r,c1,b0,samp.init) samp.bw.corr <- samp.bw$biwt.sig[1,2] / sqrt(samp.bw$biwt.sig[1,1]*samp.bw$biwt.sig[2,2]) ################## ## The Function ## ################## # this function calculates the biweight mean and covariance in any dimension # given the appropriate c1 & b0 # we will always use p=2 when looking for a standard correlation biwt.est <- function(x,n,p=2,r,c1,b0,med.init){ NAid<-FALSE d <- sqrt(mahalanobis(x,med.init$center,med.init$cov)) k <- ksolve(d,p,c1,b0) if(is.na(k)) { NAid<-TRUE med.init <- covMcd(x) d <- sqrt(mahalanobis(x,med.init$center,med.init$cov)) k <- ksolve(d,p,c1,b0)} # MCD is a more robust estimate of the center/shape # than the median which is sometimes used eps <- 1e-5 crit <- 100 iter <- 1 while (crit > eps & iter < 100) { d <- d/k biwt.mu <- apply(wtbw(d,c1)*x,2,sum,na.rm=T) / sum (wtbw(d,c1),na.rm=T) cent <- array(dim=c(n,p,p)) for (i in 1:n){ cent[i,,] <- (x[i,] - biwt.mu)%*%t(x[i,]-biwt.mu)} biwt.sig <- apply(cent*wtbw(d,c1),c(2,3),sum,na.rm=T)/ sum(vbw(d,c1),na.rm=T) d2 <- sqrt(mahalanobis(x,biwt.mu,biwt.sig)) k <- ksolve(d2,p,c1,b0) crit <- max(abs(d-(d2/k)),na.rm=T) d <- d2 iter <- iter+1} return(list(biwt.mu=biwt.mu,biwt.sig=biwt.sig))} ########################################################## #### Functions needed to run the biweight correlation #### ########################################################## ksolve <- function(d,p,c1,b0){ k <- 1 iter <- 1 crit <- 100 eps <- 1e-10 while ((crit > eps)&(iter<100)){ k.old <- k fk <- mean(rhobw(d/k,c1),na.rm=T)-b0 fkp <- -mean(psibw(d/k,c1)*d/k^2,na.rm=T) if (fkp==0) {k<-NA return(k) stop("no values close enough")} k <- k - fk/fkp if (k < 0) k <- k.old/2 crit <- abs(k-k.old) iter <- iter+1 } return(k) } rhobw <- function(x,c1){ ivec <- (abs(x)>c1) return((c1^2/6)*ivec +(1-ivec)*(x^2/2-x^4/(2*c1^2)+x^6/(6*c1^4)))} psibw <- function(x,c1){ ivec <- (abs(x)>c1) return((1-ivec)*(x*(1-(x/c1)^2)^2))} wtbw <- function(x,c1){ ivec <- (abs(x)>c1) return((1-ivec)*(1-(x/c1)^2)^2)} vbw <- function(x,c1) return(psibw(x,c1)*x) erho.bw <- function(p,c1) # gives b0 = E(rho) return(chi.int(p,2,c1)/2-chi.int(p,4,c1)/(2*c1^2)+ chi.int(p,6,c1)/(6*c1^4)+c1^2*chi.int2(p,0,c1)/6) erho.bw.p <- function(p,c1) return(chi.int.p(p,2,c1)/2-chi.int.p(p,4,c1)/(2*c1^2)+ 2*chi.int(p,4,c1)/(2*c1^3)+chi.int.p(p,6,c1)/(6*c1^4)- 4*chi.int(p,6,c1)/(6*c1^5)+c1^2*chi.int2.p(p,0,c1)/6 +2*c1*chi.int2(p,0,c1)/6) chi.int <- function(p,a,c1) return( exp(lgamma((p+a)/2)-lgamma(p/2))*2^{a/2}*pchisq(c1^2,p+a) ) chi.int2 <- function(p,a,c1) return( exp(lgamma((p+a)/2)-lgamma(p/2))*2^{a/2}*(1-pchisq(c1^2,p+a)) ) chi.int.p <- function(p,a,c1) return( exp(lgamma((p+a)/2)-lgamma(p/2))*2^{a/2}*dchisq(c1^2,p+a)*2*c1 ) chi.int2.p <- function(p,a,c1) return( -exp(lgamma((p+a)/2)-lgamma(p/2))*2^{a/2}*dchisq(c1^2,p+a)*2*c1 ) rejpt.bw <- function(p,r){ # gives c1 = ARP c1 <- 2*p iter <- 1 crit <- 100 eps <- 1e-5 while ((crit > eps)&(iter<100)){ c1.old <- c1 fc <- erho.bw(p,c1) - c1^2*r/6 fcp <- erho.bw.p(p,c1) - c1*r/3 c1 <- c1 - fc/fcp if (c1 < 0) c1 <- c1.old/2 crit <- abs(fc) iter <- iter+1 } return(c(c1,pchisq(c1^2,p),log10(1-pchisq(c1^2,p))))}