i have a 1-d array of 1's and 0's in a numpy integer array, i want to pack these values in a array of unsigned 32 bit integer values.
for example, lets say the integer array is
{0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1
i want to convert it to this
{0b01111111111000000000000111111111,0b11111111111111110000111111111111}
how can i achieve this ? thanks in advance
CodePudding user response:
I would use numpy.packbits
and numpy.frombuffer
. Result is missing first zero though, but mcsoini says it is expected though - the zero is there, just is not printed.
import numpy as np
data = [0,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,0,0,
0,0,1,1,1,1,1,1,1,1,
1,1,1]
result = np.frombuffer(np.packbits(data).tobytes(), dtype=np.uint32)
print([bin(item) for item in result])
['0b11111111000000011110000001111111', '0b11111110000011111111111111111111']
CodePudding user response:
I think your best bet is to go through strings:
d = [0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, 0]
[bin(int("".join(map(str, integer)), 2))
for integer in np.array_split(d, len(d) / 32)]
# Out:
# ['0b1111111111000000000000111111111', '0b11111111111111110000111111111110']
I added a zero to the input data to make the length a multiple of 32.
CodePudding user response:
You use bitshift to move the digit to the correct binary index. Then just accumulate the values.
(d << np.arange(len(d))).sum()
Here a more extensive version:
# first, extend to a multiple of 32
d = np.append(d, np.zeros(len(d) & 31, dtype=d.dtype))
# reshape into Nx32
d = d.reshape((-1, 32))
# broadcasted bitshift
bits = d << np.arange(32, dtype=d.dtype))
# accumulate into one value per row
bits = bits.sum(axis=1)