2

I am trying to have a numpy array with random numbers from 0 to 1:

import numpy as np
x = np.random.random((3,3))

yields

[[ 0.11874238  0.71885484  0.33656161]
 [ 0.69432263  0.25234083  0.66118676]
 [ 0.77542651  0.71230397  0.76212491]]

And, from this array, I need the row,column combinations which have values bigger than 0.3. So the expected output should look like:

(0,1),(0,2),(1,0),(1,2),(2,0),(2,1),(2,2)

To be able to extract the item (the values of x[row][column]),and tried to write the output to a file. I tried the following command:

with open('newfile.txt', 'w') as fd:
    for row in x:
        for item in row:
            if item > 0.3:
                print(item)
                for row in item:
                    for col in item:
                        print(row,column,'\n')
                        fd.write(row,column,'\n')

However, it raises an error :

TypeError: 'numpy.float64' object is not iterable

Also, I searched but could not find how to start the numpy index from 1 instead of 0. For example, the expected output would look like this:

 (1,2),(1,3),(2,1),(2,3),(3,1),(3,2),(3,3)

Do you know how to get these outputs?

2 Answers 2

3

Get the indices along first two axes that match that criteria with np.nonzero/np.where on the mask of comparisons and then simply index with integer array indexing -

r,c = np.nonzero(x>0.3)
out = x[r,c]

If you are looking to get those indices a list of tuples, zip those indices -

zip(r,c)

To get those starting from 1, add 1 and then zip -

zip(r+1,c+1)

On Python 3.x, you would need to wrap it with list() : list(zip(r,c)) and list(zip(r+1,c+1)).

Sample run -

In [9]: x
Out[9]: 
array([[ 0.11874238,  0.71885484,  0.33656161],
       [ 0.69432263,  0.25234083,  0.66118676],
       [ 0.77542651,  0.71230397,  0.76212491]])

In [10]: r,c = np.nonzero(x>0.3)

In [14]: zip(r,c)
Out[14]: [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1), (2, 2)]

In [18]: zip(r+1,c+1)
Out[18]: [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2), (3, 3)]

In [13]: x[r,c]
Out[13]: 
array([ 0.71885484,  0.33656161,  0.69432263,  0.66118676,  0.77542651,
        0.71230397,  0.76212491])

Writing indices to file -

Use np.savetxt with int format, like so -

In [69]: np.savetxt("output.txt", np.argwhere(x>0.3), fmt="%d", comments='')

In [70]: !cat output.txt
0 1
0 2
1 0
1 2
2 0
2 1
2 2

With the 1 based indexing, add 1 to np.argwhere output -

In [71]: np.savetxt("output.txt", np.argwhere(x>0.3)+1, fmt="%d", comments='')

In [72]: !cat output.txt
1 2
1 3
2 1
2 3
3 1
3 2
3 3
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your answer. However, when I use zip(r,c), it makes a zip object at memory. How can I print them out to a file?
@podedo I guess if you are on Python 3.x, you would need list(zip(r,c)). About printing to a file, I am not sure really.
@podedo Added section on writing to text file. Check that out!
1

You could use np.where, which returns two arrays (when applied to a 2D array), with indices of rows (and corresponding columns) satisfy the condition you specifiy as an argument. Then you can zip these two arrays to get back a list of tuples:

list(zip(*np.where(x > 0.3)))

If you want to add 1 to every element of every tuple (use 1 based indexing), either loop over the tuples, either add 1 to each array returned by where:

res = np.where(x > 0.3)
res[0] += 1  # adds one to every element of res[0] thanks to broadcasting
res[1] += 1
list(zip(*res))

1 Comment

It is very clean! Thank you. But how can add +1 to each tuple?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.