1

I'm very new to python and just coding in general, I'm trying to complete this assignment and there's just one more thing I need help with to finish it.

The task is to generate a square matrix with user input dimensions, and from that matrix create a new one, by removing rows and columns on intersections of which there is an element which is an absolute maximum of the elements of the matrix.

Here's what I got so far:

import numpy as np
print ("input number of rows in rmatr:")
n = int(input())
print ("input number of columns rmatr:")
m = int(input())

def form_rmatr():
    rmatr = np.ndarray(shape=(n,m),dtype=int) 
    for i in range(n):

        for j in range(m):

            rmatr[i,j] = np.random.randint(-50,50)

    return rmatr

a = form_rmatr()

print (a)

b=np.abs(np.max(a))

print ("absolute max value of rmatr = ", b)
max = (0,0)
for i in range(n):
    for j in range(m):
        if np.abs(a[i,j]) == np.abs(b):
            max = i, j            
            new_a = np.delete(np.delete(a,[i],0),[j],1)

print(new_a) 

Now, it does work, but it removes only one intersection, the first one it finds an absolute max value. I need it to remove all intersections. I tried making a while statement instead of if, but obviously, the loop just goes forever since it's searching for absolute max values in the original a matrix. The solution I need is probably to input conditions inside the np.delete function. Something along the lines np.delete(np.where...) , but I have no idea how to actually write it down.

Edit: an example of what it does would be

input number of rows in rmatr rmatr:

8
input number of columns rmatr:

8
[[ 29 -24 -42  14  12  18 -23  44]
 [-50   9 -41  -3 -14  30  11 -33]
 [ 14 -22 -43 -12  35  42   3  48]
 [-26  34  23  -9  47  -5 -33   6]
 [-33  29   0 -32 -26  24 -31   1]
 [ 15 -31 -40   1  47  30  33 -41]
 [ 48 -41   9  44  -4   0  17  -3]
 [-32 -23  31   5 -35   3   8 -31]]
absolute max value of rmatr =  48
[[-24 -42  14  12  18 -23  44]
 [  9 -41  -3 -14  30  11 -33]
 [-22 -43 -12  35  42   3  48]
 [ 34  23  -9  47  -5 -33   6]
 [ 29   0 -32 -26  24 -31   1]
 [-31 -40   1  47  30  33 -41]
 [-23  31   5 -35   3   8 -31]]

It deletes a row and column at intersections of which the number 48 is. What I need is for it to delete all intersections of rows and columns where a number 48 or -48 are. So seeing as there is one more intersection like that, I need it to look like:

    [[-24 -42  14  12  18 -23  ]
     [  9 -41  -3 -14  30  11  ]
     [ 34  23  -9  47  -5 -33  ]
     [ 29   0 -32 -26  24 -31  ]
     [-31 -40   1  47  30  33  ]
     [-23  31   5 -35   3   8  ]]
leonguide
  • 13
  • 3

2 Answers2

3

NumPy is designed to allow you to vectorize your computations. This generally means you should rarely if ever need native Python for-loops. Here is a short definition of vectorization.

You can do this in 5 lines of code:

a = np.random.randint(-50, 50, size=(n, m), dtype=int)
ne = np.abs(a) != np.abs(a).max()
cols = np.nonzero(ne.all(axis=0))[0]
rows = np.nonzero(ne.all(axis=1))[0]
new_a = a[rows[:, None], cols]

print(a)
[[ -2  20  10  10 -25]
 [-15 -24  22 -43 -37]
 [-48  29  23 -16  23]
 [-26 -25   1 -48 -32]
 [ 22  15 -24 -24 -40]]

print(new_a)
[[ 20  10 -25]
 [-24  22 -37]
 [ 15 -24 -40]]

Here's a walkthrough of the above:

Instead of creating a with a nested for-loop, we can specify its size (really, its shape) directly as a tuple. It is an (n x m) array.

ne is an array that is the same shape as a. It is False only in places that meet your condition that a given cell's maximum value is equal to the maximum absolute value of the entire array. (If I'm not interpreting that right, you should be able to revise easily.)

[[ True  True  True  True  True]
 [ True  True  True  True  True]
 [False  True  True  True  True]
 [ True  True  True False  True]
 [ True  True  True  True  True]]

Now we need the indexes of rows and columns, respectively, that contain all Trues.

print(rows)
[0 1 4]

print(cols)
[1 2 4]

Finally, you can use a bit of advanced indexing to slice a on both of these 1-dimensional arrays at once.

Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
  • 2
    @leonguide this way you also fully utilise NumPy's speed. Manually indexing and iterating NumPy arrays from Python comes with a significant overhead. – Eli Korvigo Feb 16 '18 at 19:56
-1

Hope this works-

import numpy as np
print ("input number of rowsm/columns in rmatr:")
n = int(input())
m = n
def form_rmatr():
    rmatr = np.ndarray(shape=(n,m),dtype=int)
    for i in range(n):
        for j in range(m):
            rmatr[i,j] = np.random.randint(-50,50)
    return rmatr
a = form_rmatr()
print (a)
b=np.abs(a).max()
print(b)
print ("absolute max value of rmatr = ", b)
max_rows=[]
max_cols=[]
for i in range(0,n):
    for j in range(0,m):
        if abs(a[i][j])==b:
            max_rows.append(i)
            max_cols.append(j)
a=np.delete(a,max_rows, axis=0)
a=np.delete(a,max_cols, axis=1)
print(a)
Abhisek Roy
  • 582
  • 12
  • 31
  • Actually, there is a weird issue, `b=np.abs(np.max(a))` didn't find a maximum value in absolute, it picked a number 47 even though there was a -50 in there. Any idea why might that be? – leonguide Feb 16 '18 at 19:30
  • @BradSolomon hm, since I'm late to bring the assignment in, I just pick something that works. And because I'm an absolute beginner in this, I barely understand anything that's going in in the code. But I will definitely keep what you've said in mind, and once I have more time to actually learn the code will look into it. – leonguide Feb 16 '18 at 19:37
  • Brad's code is much more optimized, and you should try to understand it in free time. There is only one rule in python-avoid for loops. – Abhisek Roy Feb 16 '18 at 19:38
  • 1
    yes, now it specifically picked a negative number, thank you again. – leonguide Feb 16 '18 at 19:41
  • @AbhisekRoy there is a much more general rule: avoid low-level C-like coding patterns. – Eli Korvigo Feb 16 '18 at 19:57
  • I'll try to avoid them. @EliKorvigo. Thanks for the advice. – Abhisek Roy Feb 16 '18 at 20:01