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!