Home > Software engineering >  How to Add Values to an Array on the off diagonal in Python?
How to Add Values to an Array on the off diagonal in Python?

Time:04-27

B <- matrix(0, S, S)
diag(B) <- -s
  
  for (i in 2:S) { # i is rows
      for(j in 1:(i-1)){ #j is colums
          a <- 1
          b<- 2
      
          B[i,j]<- a
          B[j,i] <-b    
      }  
  }

This is a code I have used to create an array in R. Where I can determine the off diagonal numbers independently. SO B[i,j]<- a does the lower off diagonal and B[j,i] <-b does the upper off diagonal.

However, I can't figure out how to do that in Python. I started by setting up like this by writing this function, but I haven't gotten anywhere near as the set up in r. I would love to set up a for loop in which I can assign values in the off diagonal (upper and lower independently.

def get_A (S,s,sigma):
    A = np.zeros((S, S)) # create a matrix with all 0 in it
    # check the type of matrix
    print(A.dtype)

    
    
    for i in range (1,S):
        
        for j in range(i-1):
            
        A[i,j]=1
        A[j,i]=2
            return A

CodePudding user response:

Using Numpy you can do it the following way:

n = 5    # Number of rows / columns
arr = np.zeros((n, n), dtype=int)  # Create an array, initially filled with zeroes
arr[np.triu_indices(n, k=1)] = 1   # Set the "upper triangle" elements to 1
arr[np.tril_indices(n, k=-1)] = 2  # Set the "lower triangle" elements to 1

The result is:

array([[0, 1, 1, 1, 1],
       [2, 0, 1, 1, 1],
       [2, 2, 0, 1, 1],
       [2, 2, 2, 0, 1],
       [2, 2, 2, 2, 0]])

Maybe you should read about triu_indices and tril_indices functions.

CodePudding user response:

With R and python you do not need for-loops:

in R:

B = matrix(1,S,S)
B - diag(S)   upper.tri(B)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    2    2    2    2
[2,]    1    0    2    2    2
[3,]    1    1    0    2    2
[4,]    1    1    1    0    2
[5,]    1    1    1    1    0

in Python:

B = np.ones((S,S))
B - np.eye(S)   np.triu(B, 1)

array([[0., 2., 2., 2., 2.],
       [1., 0., 2., 2., 2.],
       [1., 1., 0., 2., 2.],
       [1., 1., 1., 0., 2.],
       [1., 1., 1., 1., 0.]])

CodePudding user response:

You seem to want to assign different values to the diagonal and upper and lower triangles, but from your example code, you don't seem to know that range() is closed on the left and open on the right.

To assign values through the for loop, you can:

def get_A(S, s, sigma):
    A = np.zeros((S, S))
    
    for i in range(S):
        A[i, i] = s
    for i in range(1, S):
        for j in range(i):
            A[i, j] = 1
            A[j, i] = 2
    return A

When input is get_A(3, 0, 0) (I don't know what sigma means), you will get:

array([[0., 2., 2.],
       [1., 0., 2.],
       [1., 1., 0.]])

A simpler and faster way is to use np.indices and bool mask array:

def get_A(S, s, sigma):
    A = np.diag(np.repeat(s, S))
    i, j = np.indices(A.shape)

    A[i > j] = 1
    A[i < j] = 2

    return A

As shown in the answer with the highest score, use np.triu_indices and np.tril_indices are better than this.

  • Related