4

Given a 1d integer array, e.g.:

[1, 0, -1]

looking for a binary representation matrix, desired output:

[[0 1], [0 0], [1 1]]

possibly using np.binary_repr with a given fixed width. Currently np.binary_repr gives back a string and only applies to a single number at a time.

tobin = np.vectorize(np.binary_repr)
tobin(np.arange(4))
# ['0000' '0001' '0010' '0011']

2 Answers 2

1

You can use np.unpackbits:

a=np.array([-1,0,1]) # dtype is np.int32

You have to input your data as np.uint8 because that is the only data type supported by unpackbits:

bi = np.unpackbits(a[:,None].view(np.uint8), axis=1)

Original input data is 32bit, so you get 32 values per input element, crop accordingly (keeping in mind min/max values in a):

result = bi[:, :8]
array([[1, 1, 1, 1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1]], dtype=uint8)

Edit:

This works well for small numbers like the one in the answer. If you need more than 8 bits, you should read the 1st 8 elements of bi and then the 16th to 8th elements. It's a bit messy.

For a more generic solution, just better flip the array view. And cropping before unpacking will give you a some performance improvement:

def int_to_bin(arr, n_bytes=1):       
    # arr is 1-D
    arr_ = np.fliplr(arr[:, None].view(np.uint8))[:, -n_bytes:]        
    return np.unpackbits(arr_, axis=1)

You can crop the output further if you want, say, only 4 bits. This takes about 10 ms for one million arr of int32.

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

2 Comments

Thanks, this is what I had initially in mind but it needs to be able to handle arbitrary bits, not in bytes.
The minimum memory that np uses to represent an int is one byte. I think that's because of hardware, so under the hood, you are getting 8 bits whether you want them all or not. For arbitrary bits, you can simply index what you need: int_to_bin(a)[:, -4:] for 4 bits
0

Here is an explicit for loop based solution I currently have, would be keen on getting a vectorised solution.

def int_to_bin_matrix(arr: np.ndarray, width: int):
  """Return the binary representation of matrix of integer array."""
  return np.array([[int(c) for c in np.binary_repr(i, width=width)] for i in arr], dtype=np.int32)

print(int_to_bin_matrix(np.arange(-2,2), 4))

[[1 1 1 0]
 [1 1 1 1]
 [0 0 0 0]
 [0 0 0 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.