R/mantelMultiple.R

Defines functions partialCorrelation mantelMultiple

Documented in mantelMultiple partialCorrelation

mantelMultiple <- function(Y, X, permutations = 999, strata) {
## Y must be a single distance matrix, the response
## X is a list of distance matrices, the predictors (can be a list of length == 1 for a standard Mantel test)
## The Pearson product moment is the hard-wired correlation coefficient as written (though of course any statistic could be used)
## Andrew Hipp, 22 May 2008 (ahipp@mortonarb.org)

## 0. Format data
  if(class(Y) == 'list' || class(X) != 'list') stop('Y should be a solitary vector or matrix, the reponse; X should be a list of vectors or matrices in the same form; if X is solitary, still wrap it as list(X).')
  if (identical(names(X), NULL)) names(X) <- paste('X', 1:length(X), sep = '')
  Ylist <- list(Y); names(Ylist) <- 'Y'
  matrixList <- c(X, Ylist)
  pcors <- numeric(length(X)); names(pcors) <- names(X)
  pcorsDistTemp <- pcors
  RHsignif <- pcors
  LHsignif <- pcors
  pcorDistribution <- matrix(nrow = permutations, ncol = length(X), dimnames = list(seq(permutations), names(X))) 

## 1. Get the partial and multiple correlation coefficients for all items in X
  pCorMatrix = partialCorrelation(matrixList)
  for(i in names(X)) pcors[i] <- pCorMatrix[i, 'Y']
  multRsquared = Rsquared(Y, X)

## 2. Generate a distribution of partial correlation coefficients by permutation
## The following lines are modified (slightly) from vegan 1.11-2 function 'mantel.partial'
## ---------------------------------------------------------------------------------------
	N <- attributes(Y)$Size
	perm <- rep(0, permutations)
	for (i in 1:permutations) {
	  take <- permutedIndex(N, strata)
	  permvec <- as.dist(as.matrix(Y)[take, take])
	  permVeclist <- list(permvec); names(permVeclist) <- 'Y'
	  permMatrixList <- c(X, permVeclist)
	  pcorsDistTemp = partialCorrelation(permMatrixList)
	  for(j in names(X)) pcorDistribution[i,j] <- pcorsDistTemp[j, 'Y']
	#  rxy <- cor(permvec, ydis, method = method)
	#  rxz <- cor(permvec, zdis, method = method)
	#  perm[i] <- part.cor(rxy, rxz, ryz)
	  }
## ---------------------------------------------------------------------------------------

  
## 3. Calculate RH and LH significance
for(i in names(X)) {
  RHsignif[i] <- sum(pcorDistribution[,i] >= pcors[i]) / permutations
  LHsignif[i] <- sum(pcorDistribution[,i] <= pcors[i]) / permutations
  }  

output = list(pcors = pcors, partialRsquared = pcors^2, multRsquared = multRsquared, pValues = rbind(RHsignif, LHsignif))
return(output)
}


Rsquared <- function (Y, X) {
## multiple R squared for an indefinite number of X (predictor) vectors or matrices on a single Y (response) vector or matrix
    if(class(Y) == 'list' || class(X) != 'list') stop('Y should be a solitary vector or matrix, the reponse; X should be a list of vectors or matrices in the same form; if X is solitary, still wrap it as list(X).')
    Ylist <- list(Y); names(Ylist) <- 'Y'
    matrixList <- c(X, Ylist)
    matrices <- names(matrixList)
    R = matrix(nrow = length(matrices), ncol = length(matrices), dimnames = list(matrices,matrices))
    for (i in matrices) {
      for (j in matrices) {
        R[i,j] <- cor(matrixList[[i]], matrixList[[j]]) }}
    Rxx <- R[1:(length(matrices) - 1), 1:(length(matrices) - 1)]
    Rxy <- R[1:(length(matrices) - 1), length(matrices)]
    Ryx <- R[length(matrices), 1:(length(matrices) - 1)]
    R2 <- Ryx %*% solve(Rxx, Rxy)
    return(as.vector(R2))
}

partialCorrelation <- function(matrixList) {
require(corpcor)
    matrices <- names(matrixList)
    R <- matrix(nrow = length(matrices), ncol = length(matrices), dimnames = list(matrices,matrices))
    for (i in matrices) {
      for (j in matrices) {
        R[i,j] <- cor(matrixList[[i]], matrixList[[j]]) }}
    output <- cor2pcor(R, tol = 0.0001)
    dimnames(output) <- list(matrices,matrices)
    return(output)
    }

permutedIndex <- function (n, strata) 
## This is straight out of vegan 1.11-2 (originally permuted.index, renamed here in case the original function should change)
{
    if (missing(strata) || is.null(strata)) 
        out <- sample(n, n)
    else {
        out <- 1:n
        inds <- names(table(strata))
        for (is in inds) {
            gr <- out[strata == is]
            if (length(gr) > 1) 
                out[gr] <- sample(gr, length(gr))
        }
    }
    out
}
andrew-hipp/morton documentation built on April 7, 2024, 12:15 p.m.