Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing every row in a matrix

Tags:

r

I've got a matrix (mat1), say 100 rows and 100 columns; I want to create another matrix where every row is the same as the 1st row in mat1 (except that I want to keep the 1st col as the original values)

I've managed to do this using a loop:

mat2 <- mat1

for(i in 1:nrow(mat1))
{
    mat2[i,2:ncol(mat2)] <- mat1[1,2:ncol(mat1)]
}

this works and produces the result I expect; however, I'd have thought there should be a way to do it without a loop; I've tried:

mat2 <- mat1
mat2[c(2:100),2:ncol(mat2)] <- mat1[1,2:ncol(mat1)]

Can someone point out my error?!

Thanks,
Chris

like image 843
ChrisW Avatar asked Dec 27 '22 15:12

ChrisW


1 Answers

The problem is the way R fills matrices, by columns. Here is a simple example that illustrates this:

mat1 <- matrix(1:9, ncol = 3)
mat2 <- matrix(1:9, ncol = 3)

mat2[-1, -1] <- mat1[1, -1]
mat2

> mat2
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    4    4
[3,]    3    7    7

mat1[1, -1] is the vector 4,7, which you can see that R has used to fill the bit of mat2 column-wise. You wanted a row-wise operation.

One solution is to replicate the replacement vector as many times as is required:

> mat2[-1, -1] <- rep(mat1[1, -1], each = nrow(mat1)-1)
> mat2
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    4    7
[3,]    3    4    7

This works because the rep() call replicates each value in the vector when we use the "each" argument, instead of replicating (repeating) the vector:

> rep(mat1[1, -1], each = nrow(mat1)-1)
[1] 4 4 7 7

The default behaviour would also give the wrong answer:

> rep(mat1[1, -1], nrow(mat1)-1)
[1] 4 7 4 7

In part, the problem you are seeing is also the way R extends arguments to the appropriate length for the replacement. R actually, and silently, extended the replacement vector exactly in the way rep(mat1[1, -1], nrow(mat1)-1) does, which when coupled with the fill-by-column principle gave the behaviour you saw.

like image 153
Gavin Simpson Avatar answered Dec 31 '22 04:12

Gavin Simpson