Creating a "bitmask" from multiple numpy logical arrays

I am trying to convert several masks (boolean arrays) to a bitmask with numpy, while it theoretically works, I feel like I am performing too many operations.

For example, to create a bitmask, I use:

import numpy as np flags = [ np.array([True, False, False]), np.array([False, True, False]), np.array([False, True, False]) ] flag_bits = np.zeros(3, dtype=np.int8) for idx, flag in enumerate(flags): flag_bits += flag.astype(np.int8) << idx # equivalent to flag * 2 ** idx 

Which gives me the expected "bit mask":

 >>> flag_bits array([1, 6, 0], dtype=int8) >>> [np.binary_repr(bit, width=7) for bit in flag_bits] ['0000001', '0000110', '0000000'] 

However, I feel that especially casting int8 and adding with the flag_bits array flag_bits too complicated. So I wanted to ask if there is any NumPy function that I missed that could be used to create such an array of "bitmasks"?

Note. I call an external function that expects such a bitmask, otherwise I would stick with boolean arrays.

+5
source share
3 answers

Here's an approach to directly accessing a bitmask of a string with boolean-indexing -

 out = np.repeat('0000000',3).astype('S7') out.view('S1').reshape(-1,7)[:,-3:] = np.asarray(flags).astype(int)[::-1].T 

Run Example -

 In [41]: flags Out[41]: [array([ True, False, False], dtype=bool), array([False, True, False], dtype=bool), array([False, True, False], dtype=bool)] In [42]: out = np.repeat('0000000',3).astype('S7') In [43]: out.view('S1').reshape(-1,7)[:,-3:] = np.asarray(flags).astype(int)[::-1].T In [44]: out Out[44]: array([b'0000001', b'0000110', b'0000000'], dtype='|S7') 

Using the same matrix multiplication strategy described in detail in the @Marat solution , but using a vector scaling array that gives us flag_bits -

 np.dot(2**np.arange(3),flags) 
+1
source

How about this (added conversion to int8 if necessary):

 flag_bits = (np.transpose(flags) << np.arange(len(flags))).sum(axis=1)\ .astype(np.int8) #array([1, 6, 0], dtype=int8) 
+2
source
 >>> x = np.array(2**i for i in range(1, np.shape(flags)[1]+1)) >>> np.dot(flags, x) array([1, 2, 2]) 

How it works: in a bitmask, each bit is actually the source element of the array multiplied by a power of 2 in accordance with its position, for example. 4 = False * 1 + True * 2 + False * 4 . Effectively, this can be represented as matrix multiplication, which is really effective in numpy.

So, the first line is an understanding of the list for creating these weights: x = [1, 2, 4, 8, ... 2 ^ (n + 1)].

Then each line in the flags is multiplied by the corresponding element in x, and everything is summed (this is how matrix multiplication works). At the end we get a bitmask

+2
source

Source: https://habr.com/ru/post/1263857/


All Articles