Search code examples
rmatrixt-test

T test for two lists of matrices


I have two lists of matrices (list A and list B, each matrix is of dimension 14x14, and list A contains 10 matrices and list B 11) and I would like to do a t test for each coordinate to compare the means of each coordinate of group A and group B. As a result I would like to have a matrix of dimension 14x14 which contains the p value associated with each t test.

Thank you in advance for your answers.


Solution

  • Here's a method using a for loop and then applying the lm() function.

    First we'll generate some fake data as described in the question.

    #generating fake matrices described by OP
    listA <- vector(mode = "list", length = 10)
    listB <- vector(mode = "list", length = 10)
    for (i in 1:10) {
       listA[[i]] <-  matrix(rnorm(196),14,14,byrow = TRUE)
    }
    for (i in 1:11) {
      listB[[i]] <-  matrix(rnorm(196),14,14,byrow = TRUE)
    }
    

    Then we'll unwrap each matrix as described by dcarlson in a for loop.

    Unwrapped.Mats <- NULL
    for (ID in 1:10) {
      unwrapped <- as.vector(as.matrix(listA[[ID]])) #Unwrapping each matrix into a vector
      withID <- c(ID, "GroupA", unwrapped) #labeling it with ID# and which group it belongs to 
      UnwrappedCorMats <- rbind(Unwrapped.Mats, withID)
    }
    for (ID in 1:11) {
      unwrapped <- as.vector(as.matrix(listB[[ID]]))
      withID <- c(PID, "GroupB", unwrapped)
      UnwrappedCorMats <- rbind(UnwrappedCorMats, withID)
    }
    

    Then write and apply a function to run lm(). lm() is statistically equivalent to an unpaired t-test in this context but I'm using it to be more easily adapted into a mixed effect model if anyone wants to add mixed effects.

    UnwrappedDF <- as.data.frame(UnwrappedCorMats)
    lmPixel2Pixel <- function(i) { #defining function to run lm
      lmoutput <-   summary(lm(i ~ V2, data= UnwrappedDF)) 
      lmoutputJustP <- lmoutput$coefficients[2,4] #Comment out this line to return full lm output rather than just p value
    }
    
    Vector_pvals <- sapply(UnwrappedDF[3:length(UnwrappedDF)], lmPixel2Pixel)
    

    Finally we will reform the vector into the same shape as the original matrix for more easily interpreting results

    LM_mat.again <- as.data.frame(matrix(Vector_pvals, nrow = nrow(listA[[1]]), ncol = ncol(listA[[1]]), byrow = T)) 
    colnames(LM_mat.again) <- colnames(listA[[1]]) #if your matrix has row or column names then restoring them is helpful for interpretation
    rownames(LM_mat.again) <- colnames(listB[[1]])
    
    head(LM_mat.again)
    

    I'm sure there are faster methods but this one is pretty straight forward and I was surprised there weren't answers for this type of operation yet