Home > database >  R: create diagonal from 1 to 10 in matrix -> returns only last value
R: create diagonal from 1 to 10 in matrix -> returns only last value

Time:05-15

I need to modify a matrix filled with random numbers so that the resulting matrix has a diagonal with the numbers 1 to 10 and everywhere else there are supposed to be zeros. I am almost done but the diagonal only shows the last value 10 instead of the numbers 1 to 10. I know I need to cache the result somehow but I don't know how to do that.

rand_mat = matrix(sample(1:50, 100, replace = TRUE), nrow=10, ncol=10)
#10x10 matrix filled with random numbers


for (i in 1:nrow(rand_mat)) {
  #for each row
  for (j in 1:ncol(rand_mat)) {
    #for each column
    for (o in 1:10){
      #go through numbers 1 to 10 for the diagonal
      
      if(i == j){
        #if row matches column -> diagonal
      
      rand_mat[i,j] = o
      #assign numbers 1 to 10 in the diagonal
      

      }else{
        
        rand_mat[i,j] = 0
        #if location is not in the diagonal assign 0
        
      }
      
    }
    
  }
  
}

This is the current result:

> print(rand_mat)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   10    0    0    0    0    0    0    0    0     0
 [2,]    0   10    0    0    0    0    0    0    0     0
 [3,]    0    0   10    0    0    0    0    0    0     0
 [4,]    0    0    0   10    0    0    0    0    0     0
 [5,]    0    0    0    0   10    0    0    0    0     0
 [6,]    0    0    0    0    0   10    0    0    0     0
 [7,]    0    0    0    0    0    0   10    0    0     0
 [8,]    0    0    0    0    0    0    0   10    0     0
 [9,]    0    0    0    0    0    0    0    0   10     0
[10,]    0    0    0    0    0    0    0    0    0    10
> 

CodePudding user response:

Your innermost loop is unnecessary. When you are looping through j, you are looping through each cell in row i. So you need only assign the value i to the cell if i == j and 0 otherwise. You don't need the variable o at all.

So a fixed-up version of your code might be:

rand_mat = matrix(sample(1:50, 100, replace = TRUE), nrow=10, ncol=10)

for (i in 1:nrow(rand_mat)) {
  #for each row
  for (j in 1:ncol(rand_mat)) {
    #for each column
      if(i == j) {
        #if row matches column -> diagonal
      
         rand_mat[i,j] <- i
         #assign row number in the diagonal
      } else {
        
        rand_mat[i,j] = 0
        #if location is not in the diagonal assign 0
        
      }
   }
}

rand_mat
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#>  [1,]    1    0    0    0    0    0    0    0    0     0
#>  [2,]    0    2    0    0    0    0    0    0    0     0
#>  [3,]    0    0    3    0    0    0    0    0    0     0
#>  [4,]    0    0    0    4    0    0    0    0    0     0
#>  [5,]    0    0    0    0    5    0    0    0    0     0
#>  [6,]    0    0    0    0    0    6    0    0    0     0
#>  [7,]    0    0    0    0    0    0    7    0    0     0
#>  [8,]    0    0    0    0    0    0    0    8    0     0
#>  [9,]    0    0    0    0    0    0    0    0    9     0
#> [10,]    0    0    0    0    0    0    0    0    0    10

Or, more succinctly:

for (i in 1:nrow(rand_mat)) 
  for (j in 1:ncol(rand_mat)) 
      rand_mat[i, j] <- if(i == j) i else 0

Created on 2022-05-14 by the reprex package (v2.0.1)

CodePudding user response:

Using only functions you used in your question:

rand_mat = matrix(sample(1:50, 100, replace = TRUE), nrow=10, ncol=10)
rand_mat <- matrix(0, 10, 10)        # Make all the elements 0.
for(i in 1:10) rand_mat[i, i] <- i   # Replace the diagonal elements

CodePudding user response:

Although this is not an efficent way to do this (as noted in comments), you can fix your code by removing the innermost loop and replacing it with an assignment:

for (i in 1:nrow(rand_mat)) {
  for (j in 1:ncol(rand_mat)) {
    rand_mat[i,j] = if(i == j) i else 0 
      }
    }

CodePudding user response:

I got it thanks to @dcarlson Their code was definitely a lot shorter but I really wanted to use my code to see what I was doing wrong. Turns out I had to write rand_mat[o,o] = o instead of rand_mat[i,j] = o in the if-else-loop. So the code now looks like this:

rand_mat = matrix(sample(1:50, 100, replace = TRUE), nrow=10, ncol=10)
#10x10 matrix filled with random numbers


for (i in 1:nrow(rand_mat)) {
  #for each row
  for (j in 1:ncol(rand_mat)) {
    #for each column
    for (o in 1:10){
      #go through numbers 1 to 10 for the diagonal
      
      if(i == j){
        #if row matches column -> diagonal
      
      rand_mat[o,o] = o
      #assign numbers 1 to 10 in the diagonal

      }else{
        
        rand_mat[i,j] = 0
        #if location is not in the diagonal assign 0
        
      }
      
    }
    
  }
  
}

and the result looks like when I tried it with the code from @dcarlson

> print(rand_mat)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1    0    0    0    0    0    0    0    0     0
 [2,]    0    2    0    0    0    0    0    0    0     0
 [3,]    0    0    3    0    0    0    0    0    0     0
 [4,]    0    0    0    4    0    0    0    0    0     0
 [5,]    0    0    0    0    5    0    0    0    0     0
 [6,]    0    0    0    0    0    6    0    0    0     0
 [7,]    0    0    0    0    0    0    7    0    0     0
 [8,]    0    0    0    0    0    0    0    8    0     0
 [9,]    0    0    0    0    0    0    0    0    9     0
[10,]    0    0    0    0    0    0    0    0    0    10
> 

But as I learnt from @Allan Cameron you don't need the variable o so you don't even need the third for-loop:

rand_mat = matrix(sample(1:50, 100, replace = TRUE), nrow=10, ncol=10)

for (i in 1:nrow(rand_mat)) {
  #for each row
  for (j in 1:ncol(rand_mat)) {
    #for each column
    if(i == j) {
      #if row matches column -> diagonal
      
      rand_mat[i,j] <- i
      #assign row number in the diagonal
      
    } else {
      
      rand_mat[i,j] = 0
      #if location is not in the diagonal assign 0
      
    }
  }
}

The result is the same. Thank you for your help!

  • Related