Binary Numpy Array to List of Integers

Binary numpy array to list of integers?

I once asked a similar question here. Here was my answer, adapted for your question:

def bool2int(x):
y = 0
for i,j in enumerate(x):
y += j<<i
return y

In [20]: a
Out[20]:
array([[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 1],
[1, 1, 1, 1]])

In [21]: [bool2int(x[::-1]) for x in a]
Out[21]: [12, 4, 7, 15]

How to change a binary numpy array into an int?

At first, convert Numpy array to string by simply appending elements.
Then, using int(), recast the string using base of 2.

koo = np.random.randint(2, size=10)
print(koo)
binaryString = ""
for digit in koo:
binaryString += str(digit)
print(binaryString)
decimalString = int(binaryString, base=2)
print(decimalString)

An example run:

[0 0 1 0 1 0 0 0 0 0]
0010100000
160

Convert binary (0|1) numpy to integer or binary-string?

One way would be using dot-product with 2-powered range array -

b.dot(2**np.arange(b.size)[::-1])

Sample run -

In [95]: b = np.array([1,0,1,0,0,0,0,0,1,0,1])

In [96]: b.dot(2**np.arange(b.size)[::-1])
Out[96]: 1285

Alternatively, we could use bitwise left-shift operator to create the range array and thus get the desired output, like so -

b.dot(1 << np.arange(b.size)[::-1])

If timings are of interest -

In [148]: b = np.random.randint(0,2,(50))

In [149]: %timeit b.dot(2**np.arange(b.size)[::-1])
100000 loops, best of 3: 13.1 µs per loop

In [150]: %timeit b.dot(1 << np.arange(b.size)[::-1])
100000 loops, best of 3: 7.92 µs per loop

Reverse process

To retrieve back the binary array, use np.binary_repr alongwith np.fromstring -

In [96]: b = np.array([1,0,1,0,0,0,0,0,1,0,1])

In [97]: num = b.dot(2**np.arange(b.size)[::-1]) # integer

In [98]: np.fromstring(np.binary_repr(num), dtype='S1').astype(int)
Out[98]: array([1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1])

Converting Binary Numpy Array into Unsigned Integer

We could slice out the first 4 columns and last 8 columns and use np.packbits separately on those. Then, scale the first slice to account for them being the most-significant block among them and add with the second slice.

Hence, the implementation would be -

slice0 = np.packbits(b[:,:-8], axis=-1).astype(np.uint16) * 16
slice1 = np.packbits(b[:,-8:], axis=-1).astype(np.uint16)
out = slice0 + slice1

Alternatively, using sum-redcution with matrix-multiplication -

b.dot(2**np.arange(b.shape[1]-1,-1,-1))

Sample run -

In [1045]: b
Out[1045]:
array([[0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0]], dtype=uint8)

In [1046]: slice0 = np.packbits(b[:,:-8], axis=-1).astype(np.uint16) * 16
...: slice1 = np.packbits(b[:,-8:], axis=-1).astype(np.uint16)
...: out = slice0 + slice1
...:

In [1047]: out.ravel()
Out[1047]: array([1786, 248, 248, 250, 248, 248, 248, 248, 1272, 760])

In [1048]: b.dot(2**np.arange(b.shape[1]-1,-1,-1))
Out[1048]: array([1786, 248, 248, 250, 248, 248, 248, 248, 1272, 760])

Converting a numpy array of zeros and ones into an array of binary numbers

np.packbits does that. However, the bits of resulting array are stored in block of np.uint8 items. This means that a.shape[1] <= 8 must be true. Moreover, it packs bits on the right (in bigendian mode) so you need to shift the values. Here is the resulting code:

np.packbits(a, bitorder='big', axis=1) >> (8-a.shape[1])

If you need the code to work with a.shape[1] > 8, then you can write a Numba code based on this previous post.

Vectorized conversion of decimal integer array to binary array in numpy

The quickest way I've found (so far) is to use the pd.Series.apply() function.

Here are the testing results:

import pandas as pd
import numpy as np

x = np.random.randint(1,10000000,1000000)

# Fastest method
%timeit pd.Series(x).apply(bin)
# 135 ms ± 539 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

# rafaelc's method
%timeit [np.binary_repr(z) for z in x]
# 725 ms ± 5.31 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# aparpara's method
binary_repr_v = np.vectorize(np.binary_repr)
%timeit binary_repr_v(x, 8)
# 7.46 s ± 24.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Expand 2-D Numpy integer Array as binary but in parallel

Came up with this approach:

def expand_multi_bin(a):
# Create result array
n = np.max(a, axis=0).sum()
d = a.shape[0]
newa = np.zeros(d*n).reshape(d,n)

row=0
for x in np.nditer(a, flags=['external_loop'], order='F'):
# Iterate each column
for idx,c in enumerate(np.nditer(x)):
# Store it to the result array
newa[idx,row:row+c] = np.ones(c)
row += np.max(x)

return newa

Though, given the multiple loops, highly skeptical that this is the best approach.

Convert a NumPy array to a binary array with the condition of each element existing in a list

Check out https://numpy.org/doc/stable/reference/generated/numpy.isin.html

arr=np.array([[23,43,1],[43,5,0],[5,0,0]])
l = [5,43]
np.isin(arr, l).astype(int)
#array([[0, 1, 0],
# [1, 1, 0],
# [1, 0, 0]])

convert each element in array to binary python

Numpy has a fast function np.binary_repr() that does what you want for an individual number. You can apply it to an array with np.vectorize():

import numpy as np

l = np.arange(12).reshape([3, 4])
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])

np.vectorize(np.binary_repr)(l, 8)
# array([['00000000', '00000001', '00000010', '00000011'],
# ['00000100', '00000101', '00000110', '00000111'],
# ['00001000', '00001001', '00001010', '00001011']], dtype='<U8')

Convert NumPy array to 0 or 1 based on threshold

np.where

np.where(a > 0.5, 1, 0)
# array([0, 0, 0, 1, 1, 1])


Boolean basking with astype

(a > .5).astype(int)
# array([0, 0, 0, 1, 1, 1])


np.select

np.select([a <= .5, a>.5], [np.zeros_like(a), np.ones_like(a)])
# array([ 0., 0., 0., 1., 1., 1.])


Special case: np.round

This is the best solution if your array values are floating values between 0 and 1 and your threshold is 0.5.

a.round()
# array([0., 0., 0., 1., 1., 1.])


Related Topics



Leave a reply



Submit