1

It is supposed to make an n x n matrix with 2's along its diagonal and -1 on the first upper and lower diagonal.

 M <- function(n){ m <- diag(x = 2, ncol = n, nrow = n) i <- 1 for(i in 1:n-1){ a <- i b <- i + 1 m[a, b] <- -1 m[b, a] <- -1 i <- i + 1 } return(m) } 

it returns for example with n = 5, a 5 x 5 matrix

M(5) [,1] [,2] [,3] [,4] [,5] [1,] 2 -1 0 0 0 [2,] -1 2 -1 0 0 [3,] 0 -1 2 -1 0 [4,] 0 0 -1 2 -1 [5,] 0 0 0 -1 2 

I would like my function to return the same thing but without the for-loop.

5
  • 2
    How exactly do you want to vectorize it? Do you want it to work for a vector n rather than a single value? It's unclear what your desired result is here. Commented Dec 17, 2020 at 20:50
  • Perhaps Vectorize(M)(5:6) Commented Dec 17, 2020 at 20:50
  • I edited my original post to maybe help explain what I want. I don't want to use a for loop in my function. Commented Dec 17, 2020 at 20:52
  • BTW, your 1:n-1. Do you intend for that to be (1:n)-1 (starting at 0) or 1:(n-1) (starting at 1)? Commented Dec 17, 2020 at 21:03
  • It is supposed to 1:(n-1), starting at 1 Commented Dec 17, 2020 at 21:06

2 Answers 2

4

So you simply mean you don't want to use the for-loop. In that case, you could try:

M <- function(n){ mat <- diag(2, n) mat[abs(row(mat) - col(mat)) == 1] <- -1 mat } M(5) [,1] [,2] [,3] [,4] [,5] [1,] 2 -1 0 0 0 [2,] -1 2 -1 0 0 [3,] 0 -1 2 -1 0 [4,] 0 0 -1 2 -1 [5,] 0 0 0 -1 2 

or even

M <- function(n){ mat <- diag(2, n) u <- col(mat) == row(mat) + 1 mat[u|t(u)] <- -1 mat } 
Sign up to request clarification or add additional context in comments.

Comments

2

Not quite as fancy as Onyambu's, but we can build the indexes directly:

M = function(n){ m = diag(x = 2, ncol = n, nrow = n) x = cbind(2:n, 1:(n - 1)) m[rbind(x, x[, 2:1])] = -1 m } M(5) # [,1] [,2] [,3] [,4] [,5] # [1,] 2 -1 0 0 0 # [2,] -1 2 -1 0 0 # [3,] 0 -1 2 -1 0 # [4,] 0 0 -1 2 -1 # [5,] 0 0 0 -1 2 

6 Comments

I do perceive that this will be faster than my code if n is large. +1. Just curious. How do you manage to add # before each line of the output?
Ugh. I copy/paste the result from console to my editor window, then use a hotkey to comment it. It's not too bad, but I wish it was smoother.
Thanks. Thought it is a feature provided by stackoverflow
@Onyambu, check out my "overflow" package. soread() creates a data.frame from (most) copy-and-paste tables in your clipboard; sodput() copies an object to your clipboard ready to paste into a question; soanswer() copies the expression and your result to your clipboard, ready to paste into an answer.
@GregorThomas, try it out and let me know what you think of it. I like that it captures the output to your clipboard ready to paste (including padding with 4 spaces and so on for markdown). soread needs some updates now that the big players (data.table and dplyr) have options to print information about the column types.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.