Reputation: 31
I have a matrix holding numerical data with 7 columns, and I want to calculate the mean of selected entries of each row (i.e. only 2 numbers from each row). Another matrix contains information of which entries are selected for each row. What's the best way to do this in R?
a b c d e f g
[1,] 0.0068 0.0240 0.0014 0.0035 0.0029 0.0293 0.0384
[2,] 0.0197 0.0325 0.0016 0.0163 0.0030 0.0234 -0.0937
[3,] -0.0194 -0.0265 0.0045 -0.0068 0.0029 0.0265 0.0997
[4,] 0.0048 0.0540 0.0015 0.0030 0.0031 -0.0090 0.0580
[5,] 0.0369 0.0112 0.0015 0.0072 0.0029 0.0597 -0.0134
[6,] -0.0025 -0.0325 0.0014 0.0031 0.0034 0.0757 0.0385
[,1] [,2]
[1,] 2 1
[2,] 2 7
[3,] 2 6
[4,] 6 7
[5,] 7 2
[6,] 7 6
Upvotes: 2
Views: 105
Reputation: 11140
Here's one generalized way using sapply
from base R which will work for any number of rows and columns in index matrix -
sapply(1:nrow(inx), function(x) {
mean(mat[x, inx[x, ]])
})
[1] 22 20 27 22 11 27
Data -
set.seed(1)
mat <- matrix(1:42, ncol = 7)
inx <- matrix(sample(7, 2*6, TRUE), ncol = 2)
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1 7 13 19 25 31 37
[2,] 2 8 14 20 26 32 38
[3,] 3 9 15 21 27 33 39
[4,] 4 10 16 22 28 34 40
[5,] 5 11 17 23 29 35 41
[6,] 6 12 18 24 30 36 42
inx
[,1] [,2]
[1,] 2 7
[2,] 3 5
[3,] 5 5
[4,] 7 1
[5,] 2 2
[6,] 7 2
Upvotes: 1
Reputation: 76402
You can index matrices with another matrix. In this case your index matrix will give 2 index matrices, as in the function below.
First, some data, since you have not posted in a convenient, copy&paste able way.
set.seed(1234)
mat <- matrix(rnorm(6*7), ncol = 7)
inx <- matrix(sample(7, 2*6, TRUE), ncol = 2)
Now the problem.
inxMeans <- function(X, I, na.rm = FALSE){
inx1 <- cbind(seq_len(nrow(I)), I[, 1])
inx2 <- cbind(seq_len(nrow(I)), I[, 2])
rowMeans(cbind(X[inx1], X[inx2]), na.rm = na.rm)
}
inxMeans(mat, inx)
#[1] -0.9916598 -0.2410865 -0.4293729 -0.7624569 -0.2461655 -0.2812934
It's possible to generalize the function above to k
columns.
inxMeans2 <- function(X, I, na.rm = FALSE){
seq_nr <- seq_len(nrow(X))
res <- apply(I, 2, function(x) X[cbind(seq_nr, x)])
rowMeans(res, na.rm = na.rm)
}
k <- 4
inx_k <- matrix(sample(7, k*6, TRUE), ncol = k)
inxMeans2(mat, inx_k)
#[1] -0.30121207 1.29338960 -0.05008767 -0.95088480 1.08333762
#[6] -0.26516481
Upvotes: 3