wtrs
wtrs

Reputation: 329

R - Dividing columns of matrix list by vector list

I have a list of matrices and a list of vectors, and I want to divide the columns of each matrix with the corresponding vector element.

For example, given

set.seed(230)
data <- list(cbind(c(NA, rnorm(6)),c(rnorm(6),NA)), cbind(runif(7), runif(7)))
divisors <- list(c(0.5,2), c(3,4))

I'm looking for a vectorized function that produces output that looks the same as

for(i in 1:length(data)){
  for(j in 1:ncol(data[[i]])){data[[i]][,j] <- data[[i]][,j] / divisors[[i]][j]}
}

i.e.

[[1]]
            [,1]        [,2]
[1,]          NA  0.28265752
[2,] -0.46967014 -0.07132588
[3,]  0.20253439 -0.37432527
[4,]  0.65736410  0.06630705
[5,]  0.72349294  0.67202129
[6,]  0.88532648 -0.80892508
[7,]  0.08162027          NA

[[2]]
           [,1]       [,2]
[1,] 0.26597435 0.18120979
[2,] 0.31213250 0.16493883
[3,] 0.19250804 0.14104145
[4,] 0.21196882 0.10172964
[5,] 0.10389773 0.04979742
[6,] 0.02754329 0.15064043
[7,] 0.25771766 0.23042586

The closest I have been able to come is

Map(`/`, data, divisors)

But that divides rows (rather than columns) of the matrix by the vector. Any help appreciated.

Upvotes: 1

Views: 515

Answers (1)

Gregor Thomas
Gregor Thomas

Reputation: 145805

Transpose your matrices before and after:

lapply(Map(`/`, lapply(data, t), divisors), t)
# [[1]]
#             [,1]        [,2]
# [1,]          NA  0.28265752
# [2,] -0.46967014 -0.07132588
# [3,]  0.20253439 -0.37432527
# [4,]  0.65736410  0.06630705
# [5,]  0.72349294  0.67202129
# [6,]  0.88532648 -0.80892508
# [7,]  0.08162027          NA
# 
# [[2]]
#            [,1]       [,2]
# [1,] 0.26597435 0.18120979
# [2,] 0.31213250 0.16493883
# [3,] 0.19250804 0.14104145
# [4,] 0.21196882 0.10172964
# [5,] 0.10389773 0.04979742
# [6,] 0.02754329 0.15064043
# [7,] 0.25771766 0.23042586

I prefer the transpose approach above, but another option is to expand your divisor vectors into matrices of the same dimensions as in data:

div_mat = Map(matrix, data = divisors, nrow = sapply(data, nrow), ncol = 2, byrow = T)
Map("/", data, div_mat)

Upvotes: 3

Related Questions