6

Given I have an multidimensional array of indices, how do I create a Boolean array from these? For the 1D case it would look like this:

a = [1,5,6]
b = somefunction(total_array_length=10, a)
>>> [False, True, False, False, False, True, True, False, False, False]

For the 2D case it would look like this:

a = [[1,3],[4,2]]
b = somefunction(total_array_length=5, a)
>>> [[False, True, False, True, False], [False, False, True, False, True]]

I want to use this to create a mask for an array. I have a multi dimensional array of dimension 8 and for the last axis I can find the indices of the elements I want to keep. In other words, I have an 8D array in which the last axis consists all indices I want to keep in the original array. Does anyone know how to do this?

In the function above the total_array_length would be equal to the length of the original array.

So how would I do this for an array of shape (23,5,76,32,1,3,8,9) with indices array of shape (23,5,76,32,1,3,8,4)? Note 4<9 but other than that it has the same dimensions.

a.shape = (23,5,76,32,1,3,8,4) 
b = somefunction(total_array_length=9, a)
b.shape =(23,5,76,32,1,3,8,9) 
3
  • It's not clear what total_array_length is and why the shape of b does not match the shape of a in either example. Also it's unclear what you are trying to say about the last axis of your 8d array. It doesn't sound analogous to your examples. Commented Dec 24, 2017 at 6:08
  • Please just try writing the code and post it if you are stuck. Don't ask us to start from scratch. Commented Dec 24, 2017 at 7:02
  • Have I made it clearer? Commented Dec 24, 2017 at 11:41

2 Answers 2

9

For the first case:

In [23]: a = [1,5,6]
In [24]: b = np.zeros(10, dtype=bool)
In [25]: b[a] = True
In [26]: b
Out[26]: array([False,  True, False, False, False,  True,  True, False, False, False], dtype=bool)

An equally simple, and possibly as fast, list version:

In [27]: [True if i in a else False for i in range(10)]
Out[27]: [False, True, False, False, False, True, True, False, False, False]

And for the list of lists just nest that list comprehension:

In [34]: [[True if i in a1 else False for i in range(5)] for a1 in a]
Out[34]: [[False, True, False, True, False], [False, False, True, False, True]]

An array version is of this second case is:

In [41]: a = [[1,3],[4,2]]
In [42]: b = np.zeros((len(a),5), bool)
In [43]: b[[[0],[1]],a]
Out[43]: 
array([[False, False],
       [False, False]], dtype=bool)
In [44]: b[[[0],[1]],a]=True
In [45]: b
Out[45]: 
array([[False,  True, False,  True, False],
       [False, False,  True, False,  True]], dtype=bool)

This, though, will only work if the sublists of a are all the same length. If they differ, I think we'll have to work with a flattened version of this. In effect turn the 2d case into the original 1d.


For a ragged a, the list version is still easy:

In [49]: a = [[1,2,3],[4,2],[1]]
In [50]: [[True if i in a1 else False for i in range(5)] for a1 in a]
Out[50]: 
[[False, True, True, True, False],
 [False, False, True, False, True],
 [False, True, False, False, False]]

But an array version is a bit more involved:

Construct 2 arrays of indices, for rows and columns:

In [53]: a0 = np.repeat(np.arange(3),[len(i) for i in a])
In [54]: a0
Out[54]: array([0, 0, 0, 1, 1, 2])
In [55]: a1 = np.hstack(a)
In [56]: a1
Out[56]: array([1, 2, 3, 4, 2, 1])

Get the equivalent raveled (1d) indexing:

In [57]: np.ravel_multi_index((a0,a1),(3,5))
Out[57]: array([ 1,  2,  3,  9,  7, 11], dtype=int32)

Apply it to a 2d array via flat:

In [58]: b = np.zeros((3,5),bool)
In [59]: b.flat[Out[57]] = True
In [60]: b
Out[60]: 
array([[False,  True,  True,  True, False],
       [False, False,  True, False,  True],
       [False,  True, False, False, False]], dtype=bool)
Sign up to request clarification or add additional context in comments.

3 Comments

How would I do this for an array of shape (23,5,76,32,1,3,8,9) with indices array of shape (23,5,76,32,1,3,8,4)? Note 4<9 but other than that it has the same dimensions.
Try reshaping the arrays into (n,4) and (n,9). Do the mapping (eg as 44). Then reshape back.
True if i in a1 else False is the same as i in a1 and it would be faster and more readable to use the latter.
2

For 1D:

n = 10
inds_all = np.arange(n)
inds = [1, 5, 6]

b = np.isin(inds_all, inds)
# array([False, True, False, False, False, True, True, False, False, False])

For 2D it's a little bit trickier, especially when the list of list-indices is of uneven sizes:

n = 5
inds_all = np.arange(len(inds)*n).reshape(len(inds), n)
inds = [[1,3], [4,2], [3]]
inds = np.concatenate(inds) + np.repeat(inds_all[:,0], list(map(len, inds)))

b = np.isin(inds_all, inds)
# array([[False,  True, False,  True, False],
#        [False, False,  True, False,  True],
#        [False, False, False,  True, False]])

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.