Little Bee
Little Bee

Reputation: 1225

Multiply a list of vectors to different matrices conditioned on the vectors' names

I have a list of 20-length vectors that I would like to multiply each of those with one of three matrices depending on the length vectors' names. Here is my unsuccessful attempt. Please suggest how I improve my code. Any help is much appreciated!

for (i in 1:length(List)){
  .$Value=ifelse(names(List) %in% c("a","b","c"),matrixA%*%.$Value,ifelse(names(List) %in% c("d","e"),matrixB%*%.$Value, matrixC%*%.$Value))
}

Part of my list and the matrices are included below.

list(a = structure(c(3, 0, 0, 5, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 1, 10, 0, 0, 1, 1), .Dim = c(20L, 1L)), b = structure(c(2, 
0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 6, 0), .Dim = c(20L, 
1L)))

matrixA <- diag(2,20)
matrixB <- diag(1,20)
matrixC <- diag(4,20)

Upvotes: 1

Views: 55

Answers (2)

IdlerGhost
IdlerGhost

Reputation: 48

So... Not sure I understand. But it seems like if the list has name a, b or c you want to multiply it to matrixA, if it's d or e you want to multiply it to matrixB and if neither, the values should be multiplied to matrixC.

Let's use your example.

zz <- list(a = structure(c(3, 0, 0, 5, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 1, 10, 0, 0, 1, 1), .Dim = c(20L, 1L)), b = structure(c(2, 
0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 6, 0), .Dim = c(20L, 
1L)))

matrixA <- diag(2,20)
matrixB <- diag(1,20)
matrixC <- diag(4,20)

This is probably not the best solution but it is a simple one. I just made a few tweaks to your ideia so it would work, a matrix needs to be protected by list() (because a list is a vector, and ifelse works with vectors) inside an ifelse() otherwise you only get the first element. This will return you a list of the results.

results <- lapply(seq_along(zz), function(i){
    ifelse(names(zz[i]) %in% c("a","b","c"),list(matrixA%*%zz[[i]]),
            ifelse(names(zz[i]) %in% c("d","e"), list(matrixB%*%zz[[i]]), list(matrixC%*%zz[[i]])))
})

I used lapply to apply the sequence to (1 to length of zz) to the defined function. For each i the function looks at the name of i element zz (zz[i] returns the element of the list with its name) and if it satisfies the condition we multiply the content of the i element of zz (zz[[i]] just returns the content of the i element of the list without its name) by a predefined matrix.

This also works and you don't need to protect the matrix using list() which is kinda of a bother.

results <- lapply(seq_along(zz), function(i){

    if(names(zz[i]) %in% c("a","b","c")) matrixA%*%zz[[i]] else 
    if(names(zz[i]) %in% c("d","e")) matrixB%*%zz[[i]]
    else matrixC%*%zz[[i]]

})

Edit: @akrun answer is way more beautiful and short.

Upvotes: 1

akrun
akrun

Reputation: 887048

May be this helps

nm1 <- paste0("matrix", toupper(names(lst1)))
Map(crossprod, lst1, mget(nm1))

Upvotes: 1

Related Questions