0

I'm trying to get the index of elements in a row that is filled.

I tried to use numpy where() function, but it's only returning the index of non-zero elements.

import numpy as np
board = np.array([[0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 2, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [2, 2, 2, 2],
                  [0, 0, 0, 0]])
for rows in board:
    if set(rows) == {2}:
        if len(set(rows)) <= 1:
            print(np.where(board == rows))

My desired output is the following:

(array([9, 9, 9, 9], dtype=int32), array([0, 1, 2, 3], dtype=int32)) 

that is, row, col.

However, I'm getting this instead:

(array([2, 9, 9, 9, 9], dtype=int32), array([1, 0, 1, 2, 3], dtype=int32)) 

As stated above, it should only get the index of elements in a filled row. The board1 is not filled with 2's, yet it's being included.

3
  • What's the expected o/p? Commented Jun 30, 2017 at 14:43
  • Your question is not quite clear. Would you please provide a sample of your desired output given the board array you listed in your question? Commented Jun 30, 2017 at 14:50
  • You actually don't need the second if, because set(rows) == {2} will only return True if the sets are equal, and the second row is {0, 2} which is not equal to {2}. Anyways, the reason it's returning more than the row you want is because board==rows still returns False, True, False, False at row 2, and so that True value is still included in the argument for np.where(). Commented Jun 30, 2017 at 15:39

3 Answers 3

1

You don't need loops for this at all. For finding the rows that are filled with something other than 0, use .all(axis=1). The axis argument tells which axis to look for matching values across:

>>> (board != 0).all(axis=1)
array([False, False, False, False, False, False, False, False, False,
    True, False], dtype=bool)

The booleans are True wherever there is a row filled with non-zero values, and False otherwise. If you take the outer product with a row array full of True values, you'll get True exactly in your matrix locations corresponding to the full row:

>>> np.outer((board!=0).all(axis=1),np.ones(board.shape[1], dtype=bool))
array([[False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [ True,  True,  True,  True],
       [False, False, False, False]], dtype=bool)

Then you can get the indices of those True values with np.where():

>>> np.where(np.outer((board!=0).all(axis=1),np.ones(board.shape[1], dtype=bool)))
(array([9, 9, 9, 9]), array([0, 1, 2, 3]))

Note that np.where() returns np.int64 values. If you want np.int32 then just assign variables and convert them:

>>> yind, xind = np.where(np.outer((board!=0).all(axis=1),np.ones(board.shape[1], dtype=bool)))
>>> yind = np.int32(yind)
>>> xind = np.int32(xind)
>>> yind, xind
(array([9, 9, 9, 9], dtype=int32), array([0, 1, 2, 3], dtype=int32))

To instead put all of these indices as tuples, use zip(*) (see here for an explanation if you're not familiar with * unpacking):

>>> [(y,x) for y,x in zip(*np.where(np.outer((board!=0).all(1), np.ones(board.shape[1]))))]
[(9, 0), (9, 1), (9, 2), (9, 3)]

And again if you need np.int32 just specify that in the comprehension:

>>> [(y.astype(np.int32),x.astype(np.int32)) for y,x in zip(*np.where(np.outer((board == 2).all(1), np.ones(board.shape[1]))))]
[(9, 0), (9, 1), (9, 2), (9, 3)]
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks to your answer, I was able to come up with this: y, x = np.where(np.outer((board == 2).all(1), np.ones(board.shape[1]))) pending_rows_indices = [(y, x) for x, y in zip(x, y)] print(pending_rows_indices) I have one more question, is there a way to write this with list comprehension? Using zip as well.
@CastFellow sure, use zip(*np.where(...)). E.g. pending_row_indices = [(y,x) for y,x in zip(*np.where(np.outer((board == 2).all(1), np.ones(board.shape[1]))))] gives you [(9, 0), (9, 1), (9, 2), (9, 3)]. I edited my post to include this at the end.
0

If i understood well you are trying to find the row where your numpy array is completely filled ( no 0 values )

so i ask of you to consider this:

import numpy as np
board = np.array([[0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 2, 0, 0],
                  [1, 1, 1, 1],   # added this one just to generalize in 
                  [0, 0, 0, 0],   # case you have numbers != 2
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [2, 2, 2, 2],
                  [0, 0, 0, 0]])
for i,rows in enumerate(board):
    if not 0 in set(rows): # changed this to work on all non zero numbers
        print(rows)
        if len(set(rows)) <= 1:
            print(i)

output:

[1 1 1 1] # first row filled
3         # its index as int ( if that's what you're looking for )
[2 2 2 2] # seconds row filled
9         # its index as int

all you needed is enumerate built-in function. Happy Coding

Comments

0

If I understood your problem correctly, you want to find the row index of a specific element in the array. So, you need the following print() statement instead of print(np.where(board == rows)).

print(np.where((board == rows).all(axis=1)))

It outputs:

(array([9], dtype=int64),)

To get the specific row number, you can do the following.

loc = np.where((board == rows).all(axis=1))
print(loc[0][0]) # prints 9

Complete program:

import numpy as np
board = np.array([[0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 2, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [0, 0, 0, 0],
                  [2, 2, 2, 2],
                  [0, 0, 0, 0]])
for rows in board:
    if set(rows) == {2}:
        print(rows)
        if len(set(rows)) <= 1:
            print(np.where((board == rows).all(axis=1)))

Comments

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.