I am trying to input a vector x onto a matrix where values of x are located on the anti-diagonal of the matrix
x = c(1,2,3,4,5)
ID = function(x){
n = length(x)
A = matrix(0, nrow = n, ncol = n)
for ( i in 1:n){
A[i, n-i 1] = x[i]
}
print(A) # Why did my code not work when I did not include this
}
Z = ID(x)
I was wondering why does my code not work when I do not include the print(A) within the function. When I don't include Print(A), my z turns out to be NULL.
Thank you in advance.
CodePudding user response:
I would do this without a loop -
x = c(1,2,3,4,5)
ID = function(x){
n = length(x)
A = matrix(0, nrow = n, ncol = n)
diag(A[nrow(A):1, ]) <- x
A
}
ID(x)
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 0 0 0 5
#[2,] 0 0 0 4 0
#[3,] 0 0 3 0 0
#[4,] 0 2 0 0 0
#[5,] 1 0 0 0 0
CodePudding user response:
If a return
statement is not encountered before the end of the function body, then the function returns the value of the last "top level" expression. When you exclude print(A)
, the last top level expression is the for
call, which returns NULL
invisibly, as documented in ?`for`
.
I would modify your function in three ways:
- Replace
matrix(0, n, n)
withmatrix(vector(typeof(x), n * n), n, n)
so that the type of the matrix result matches the type of the vector argument. - Replace the
for
loop with a vectorized subassignment. - Replace
print(A)
withA
so thatprint(ID(x))
doesn't print the matrix twice.
Hence my version of your function would look something like this:
antidiag <- function(x) {
n <- length(x)
A <- matrix(vector(typeof(x), n * n), n, n)
if (n > 0L) {
A[cbind(n:1, 1:n)] <- x
}
A
}
antidiag(1:4)
## [,1] [,2] [,3] [,4]
## [1,] 0 0 0 4
## [2,] 0 0 3 0
## [3,] 0 2 0 0
## [4,] 1 0 0 0
antidiag(1:4 > 0L)
## [,1] [,2] [,3] [,4]
## [1,] FALSE FALSE FALSE TRUE
## [2,] FALSE FALSE TRUE FALSE
## [3,] FALSE TRUE FALSE FALSE
## [4,] TRUE FALSE FALSE FALSE
antidiag(letters[1:4])
## [,1] [,2] [,3] [,4]
## [1,] "" "" "" "d"
## [2,] "" "" "c" ""
## [3,] "" "b" "" ""
## [4,] "a" "" "" ""