Reputation: 51
Is there a way to code this simplier than mine?
value = c(0,1,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0)
first = matrix(value, nrow=6)
second = matrix(rev(first),nrow=6) #reverse vector "value"
output10 = cbind(first,second)
output10
I am just very curious if there is a simplier way to code this because I find my codes "too rudimentary". Thanks.
Upvotes: 2
Views: 124
Reputation: 34763
Assuming your goal is to assign 1
on the off-diagonal elements, the approach that will scale best to massive matrices would be:
N = 100L
M = matrix(0L, N, N)
idx = seq_len(N - 1L)
M[cbind(c(idx, idx+1L), c(idx+1L, idx))] = 1L
M[1:6, 1:6]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 0 1 0 0 0 0
# [2,] 1 0 1 0 0 0
# [3,] 0 1 0 1 0 0
# [4,] 0 0 1 0 1 0
# [5,] 0 0 0 1 0 1
# [6,] 0 0 0 0 1 0
This works by using patterns to create the tuples where 1
s will be and assigning those only.
In sparse
matrix world it would be similar:
library(Matrix)
N = 1e8 # 100,000,000
idx = seq_len(N - 1L)
M = sparseMatrix(c(idx, idx + 1L), c(idx + 1L, idx))
M[1:6, 1:6]
6 x 6 sparse Matrix of class "ngCMatrix"
# [1,] . | . . . .
# [2,] | . | . . .
# [3,] . | . | . .
# [4,] . . | . | .
# [5,] . . . | . |
# [6,] . . . . | .
As a dense matrix, this would be 1e16
integer elements, or 80 petabytes, so M
(which is about 1GB) is pretty impressive to keep in memory & declare in a few seconds. Both other approaches here would fail -- row
,col
, and rev
all would create dense vectors.
Upvotes: 0
Reputation: 20811
You could create a matrix of 0s and use indexing to put in the 1s where you want
mm <- matrix(0, 6, 6)
mm[col(mm) == row(mm) + 1 | col(mm) == row(mm) - 1] <- 1
mm
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 0 1 0 0 0 0
# [2,] 1 0 1 0 0 0
# [3,] 0 1 0 1 0 0
# [4,] 0 0 1 0 1 0
# [5,] 0 0 0 1 0 1
# [6,] 0 0 0 0 1 0
Upvotes: 1
Reputation: 19071
You can directly create the result matrix from the concatenation of value
and rev(value)
:
value <- c(0,1,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0)
output10 <- matrix(c(value, rev(value)), nrow=6)
Upvotes: 5