Search code examples
rmatlabcell-arraypermute

R equivalent to permuting array dimensions permute(A, dimorder) in Matlab


I am looking for an equivalent of permute(A,dimorder) from Matlab, in order to convert some Matlab code to R. A loop entails a line that looks something like this:

x = permute(a{i}(b(i,ii),:,:,:,:,:),[2 3 4 5 6 1])

The cell array structure e.g. a{1}(1,:,:,:,:,:) results in selecting the first row of matrices within the cell array a{}. [2 3 4 5 6 1] in permute() refers to the dimorder. The documentation for the matlab function permute() including example output can be found here: https://de.mathworks.com/help/matlab/ref/permute.html

There are several functions in R referring to permutation in some way or another, but non of them seemed to be what I am looking for, though I may have gotten something wrong.


Solution

  • I believe I successfully replicated the MATLAB script in R. I don't think you actually need an equivalent for permute. In the MATLAB script, permute appears to be simply dropping excess dimensions. R does that by default unless you specify drop = FALSE when you subset an array, e.g.,

    lnA[[tau, modal]] <- a[[modal]][outcomes[modal, tau],,,drop = FALSE]
    

    If I add lnA = cell(T, NumModalities); to the MATLAB script before your final for loop and then modify the inside of the loop to be

    lnA{tau, modal} = permute(a{modal}(outcomes(modal,tau),:,:,:,:,:),[2 3 4 5 6 1]);
    

    Then I get the same array of matrices in lnA for both the MATLAB and R implementations.

    In R, I use an array of lists as the equivalent of a MATLAB 2+ dimension cell array:

    lnA1 = cell(T, 1); # MATLAB
    lnA1 <- vector("list", Time) # R    
    lnA2 = cell(T, NumModalities); # MATLAB
    lnA2 <- array(vector("list", Time*NumModalities), c(Time, NumModalities)) # R
    lnA2 <- matrix(vector("list", Time*NumModalities), Time) # R
    lnA3 = cell(T, NumModalities, 2); # MATLAB
    lnA3 <- array(vector("list", Time*NumModalities*2), c(Time, NumModalities, 2)) # R
    

    Here's the implementation:

    nat_log <- function (x) { # necessary as log(0) not defined...
      x <- log(x + exp(-16))
    }
    
    # Set up a list for D and A
    D <- list(c(1, 0),       # (left better, right better)
              c(1, 0, 0, 0)) #(start, hint, choose-left, choose-right)
    A <- c(rep(list(array(0, c(3, 2, 4))), 2), list(array(0, c(4, 2, 4))))
    
    Ns <- lengths(D) # number of states in each state factor (2 and 4)
    A[[1]][,,1:Ns[2]] <- matrix(c(1,1,  # No Hint
                                  0,0,  # Machine-Left Hint
                                  0,0), # Machine-Right Hint
                          ncol = 2, nrow = 3, byrow = TRUE)
    
    pHA <- 1
    A[[1]][,,2] <- matrix(c(0,       0,       # No Hint
                            pHA,     1 - pHA, # Machine-Left Hint
                            1 - pHA, pHA),    # Machine-Right Hint
                          nrow = 3, ncol = 2, byrow = TRUE)
    
    A[[2]][,,1:2] <- matrix(c(1, 1,   # Null
                              0, 0,   # Loss
                              0, 0),  # Win
                            ncol = 2, nrow = 3, byrow = TRUE)
    
    pWin <- 0.8
    A[[2]][,,3] <- matrix(c(0,        0,         # Null        
                            1 - pWin, pWin,      # Loss
                            pWin,     1 - pWin), # Win
                          ncol = 2, nrow = 3, byrow = TRUE)
    
    A[[2]][,,4] <- matrix(c(0,        0,        # Null        
                            pWin,     1 - pWin, # Loss
                            1 - pWin, pWin),    # Win
                          ncol = 2, nrow = 3, byrow = TRUE)
    
    for (i in 1:Ns[2]) {
      A[[3]][i,,i] <- c(1,1)
    }
    
    # Set up a list of matrices:
    a <- lapply(1:3, function(i) A[[i]]*200)
    a[[1]][,,2] <- matrix(c(0,    0,     # No Hint
                            0.25, 0.25,  # Machine-Left Hint
                            0.25, 0.25), # Machine-Right Hint
                          nrow = 3, ncol = 2, byrow = TRUE)
    
    outcomes <- matrix(c(1, 2, 1,
                         1, 1, 2,
                         1, 2, 4),
                       ncol = 3, nrow = 3, byrow = TRUE)
    
    NumModalities <- length(a)       # number of outcome factors
    Time <- 3L
    lnA <- array(vector("list", Time*NumModalities), c(Time, NumModalities))
    
    for (tau in 1:Time){
      for (modal in 1:NumModalities){
        lnA[[tau, modal]] <- a[[modal]][outcomes[modal, tau],,]
      }
    }