1

I have a 3d array, I want to find the coordinate of every element with value 1. I use numpy, and this is my array:

table = np.array([
    [
        [1,4,8,6],
        [8]],
    [
        [4],
        [9],
        [5]],
    [
        [6],
        [4]],
    [
        [2],
        [1]]])

Based on this related question I have the follow code:

print(np.argwhere(table == 1))

This code does exactly what I want (print 3d-coordinates of occurrences of value) for a 'simpler' 3d array. But doesn't work for my array.

Why does my current code not work on my array? How to get the same result on my array?

The array where it is working on:

table = np.array([
    [
        [ 1, 2, 3],
        [ 8, 4, 11]],
    [   
        [ 1, 4, 4],
        [ 8, 5, 9]],
    [
        [ 3, 8, 6],
        [ 11, 9, 8]],
    [   
        [ 3, 7, 6],
        [ 9, 3, 7]]])
3
  • 2
    Because that is an array of lists, numpy operations won't work on it directly Commented Jul 14, 2020 at 14:46
  • 1
    Check table.shape, table.dtype. It's probably not what you expect since the sublists don't have a common shape. Commented Jul 14, 2020 at 14:51
  • @a_guest thank you. Is there a way to achieve my goal with a variable shape? (something more elegant than for loops) Commented Jul 17, 2020 at 13:50

1 Answer 1

2

When you print your (first) table, the result is:

array([list([[1, 4, 8, 6], [8]]), list([[4], [9], [5]]), list([[6], [4]]),
       list([[2], [1]])], dtype=object)

i.e. it is a 1-D array, containing 4 elements of list type.

The reason that np.where can't find instances of 1 is that it looks at each element and compares it with the given value. This function, when checking particular element of the array, does not "dive" into this object (does not check individual sub-elements of an element (if it is a list)).

All that np.where does when checking an element (of list type) it to check: is this element == 1. Since it is not, then it treated as non-matching. Other elements too.

Edit following a comment as of 15.07

If you define your table as:

table2 = np.array(list([
    list([[1,4,8,6], [8,0,0,0], [0,0,0,0]]),
    list([[4,0,0,0], [9,0,0,0], [5,0,0,0]]),
    list([[6,0,0,0], [4,0,0,0], [0,0,0,0]]),
    list([[2,0,0,0], [1,0,0,0], [0,0,0,0]])]))

(with all lists of same size), Pandas is clever enough to convert it to:

array([[[1, 4, 8, 6],
        [8, 0, 0, 0],
        [0, 0, 0, 0]],

       [[4, 0, 0, 0],
        [9, 0, 0, 0],
        [5, 0, 0, 0]],

       [[6, 0, 0, 0],
        [4, 0, 0, 0],
        [0, 0, 0, 0]],

       [[2, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 0]]])

Run table.shape and you will see (4, 3, 4).

Then run table.dtype and you will see dtype('int32'), so it is now a "regular" Numpy array of ints.

In such case np.argwhere(table == 1) finds indices of cells containing just 1.

But your table is such a "weird" case that Pandas is not designed for.

To locate indices of each 1 in these (nested) lists, you may iterate over your array (using nd.iter) and look inside each element for indices of 1 if any. Something like:

it = np.nditer(table, flags=['f_index', 'refs_ok'])
for x in it:
    print(f'Index {it.index}: {x}')
    res = [(i, el.index(1)) for i, el in enumerate(x[()]) if 1 in el]
    if len(res) == 0:
        print('    Nothing found')
    else:
        print(f'    Found at: {res}')

Note that after x there is somewhat weird construction, namely [()]. The reason is that:

  • Your table is a 1-D array of objects.
  • Each element is actually a 0-D array, containing a single object (a nested list).
  • [()] is the way to get the only contained object. You access an element by index, but the index value is an empty tuple (no actual index value).

For your table the above code prints:

Index 0: [[1, 4, 8, 6], [8]]
    Found at: [(0, 0)]
Index 1: [[4], [9], [5]]
    Nothing found
Index 2: [[6], [4]]
    Nothing found
Index 3: [[2], [1]]
    Found at: [(1, 0)]

If needed, rework it to suit your needs.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.