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

Time:10-22

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.

This would be some sample Matlabcode. I put it together from another script, where this is a nested loop. So the code below may not make too much sense, but it delivers results. The relevant line (loop) is in the lower part:


D{1} = [1 0]';  % {'left better','right better'}

D{2} = [1 0 0 0]'; % {'start','hint','choose-left','choose-right'}

Ns = [length(D{1}) length(D{2})]; % number of states in each state factor (2 and 4)

for i = 1:Ns(2) 

    A{1}(:,:,i) = [1 1; % No Hint
                   0 0; % Machine-Left Hint
                   0 0];% Machine-Right Hint
end

pHA = 1; % By default we set this to 1, but try changing its value to 
          % see how it affects model behavior

A{1}(:,:,2) = [0     0;      % No Hint
               pHA 1-pHA;    % Machine-Left Hint
               1-pHA pHA];   % Machine-Right Hint

#
for i = 1:2

    A{2}(:,:,i) = [1 1;  % Null
                   0 0;  % Loss
                   0 0]; % Win
end
           

pWin = .8; % By default we set this to 1, but try changing its value to 
          % see how it affects model behavior
           
A{2}(:,:,3) = [0      0;     % Null        
               1-pWin pWin;  % Loss
               pWin 1-pWin]; % Win

           
A{2}(:,:,4) = [0      0;     % Null
               pWin 1-pWin;  % Loss
               1-pWin pWin]; % Win
           
for i = 1:Ns(2) 

    A{3}(i,:,i) = [1 1];

end


a{1} = A{1}*200;
a{2} = A{2}*200;
a{3} = A{3}*200;

a{1}(:,:,2) =  [0     0;     % No Hint
               .25   .25;    % Machine-Left Hint
               .25   .25];   % Machine-Right Hint

outcomes= [1,2,1;
           1,1,2;
           1,2,4]

NumModalities = numel(a);   
T = 3

%RELEVANT PART:
       
for tau = 1:T
for modal = 1:NumModalities
lnA = permute(a{modal}(outcomes(modal,tau),:,:,:,:,:),[2 3 4 5 6 1])
%lnA = permute(nat_log(a{modal}(outcomes(modal,tau),:,:,:,:,:)),[2 3 4 5 6 1])
% with nat_log
end
end

% natural log that replaces zero values with very small values for numerical reasons.
function y = nat_log(x)
y = log(x exp(-16));
end

My attempt in R looks like this:

nat_log = function (x) { # necessary as log(0) not defined...
  x = log(x exp(-16))
}

# Setup a list for D  
D = vector("list", 2*1)
dim(D) =  matrix(c(2,1))

D[[1,1]] = t(matrix(c(1, 0)))  
D[[2,1]] = t(matrix(c(1, 0, 0, 0))) 

# Setup a list:
A = vector("list", 3*4)
dim(A) = matrix(c(3,4))

Ns = t(matrix(c(ncol(D[[1]]), ncol(D[[2]])))) 
Ns


### A[1,1:4]

for (i in 1:Ns[,2]){
  # [[i,,]] for all behavior states
  A[[1,i]] <- matrix(c(1,1,     # No Hint
                       0,0,     # Machine-Left Hint
                       0,0),    # Machine-Right Hint
                     ncol = 2, nrow = 3, byrow = TRUE)
}


### A[1,2]
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)

for (i in 1:2){
  
  A[[2,i]] = matrix(c( 1, 1,   # Null
                       0, 0,   # Loss
                       0, 0),  # Win
                    ncol = 2, nrow = 3, byrow = TRUE) 
}


pWin = .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]){ 
  
  # x will be added to a 2*4 Matrix  
  x = matrix(c(1,1), ncol = 2, nrow = 1, byrow=TRUE)                                
  A3 = matrix(c(0,0, 0,0 ,0,0, 0,0), # c('start','hint','choose-left','choose-right')
              ncol = 2, nrow = 4, byrow=TRUE)  
  #y = A3[col = i]
  A3[i,] = 1
  A[[3,i]] <- A3
  
}

# See to understand the consequence of the loop
A[3,]
A 

# Setup a list of lists:
a = vector("list", 3*4)
dim(a) = matrix(c(3,4))
a

for (i in 1:4){
  apre = as.matrix(A)
  a[[1,i]] = apre[[1,i]]*200
  a[[2,i]] = apre[[2,i]]*200
  a[[3,i]] = apre[[3,i]]*200
}

a[[1,2]] =  matrix(c(0,     0,    # No Hint
                     .25,   .25,    # Machine-Left Hint
                     .25,   .25),   # Machine-Right Hint
                   nrow = 3, ncol = 2, byrow = TRUE)
a
NumModalities = nrow(a)       # number of outcome factors

Time = 3

outcomes = matrix(c(1,2,1,
             1,1,2,
             1,2,4), ncol = 3, nrow = 3, byrow = TRUE)

# RELEVANT PART:

lnA = vector("list", 2*4)
dim(lnA) = matrix(c(2,4))

x = vector("list",2*4)
dim(x) = matrox(c(2,4))

for (tau in 1:Time){
for (modal in 1:NumModalities){
x = a[[modal]][outcomes[[modal,tau]]]
lnA = aperm(as.array(x),c(2, 3, 4, 5, 6, 1))
}
}
as.array(x)
is.array(x)
lnA

CodePudding user response:

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],,]
  }
}
  • Related