0

I'm having a binary MxN matrix like the following:

matrix([[0, 0, 0, ..., 0, 0, 0],
    [0, 1, 0, ..., 0, 0, 0],
    [0, 0, 1, ..., 0, 0, 0],
    ..., 
    [0, 0, 0, ..., 1, 0, 0],
    [0, 0, 0, ..., 0, 0, 0],
    [0, 0, 0, ..., 0, 0, 1]])

How can I convert this matrix row-wise to the integer representation? The goal is to get a Mx1 matrix. Each row contains the integer representation of the previous binary row.

Razer
  • 7,843
  • 16
  • 55
  • 103
  • 1
    possible duplicate of [Binary numpy array to list of integers?](http://stackoverflow.com/questions/15505514/binary-numpy-array-to-list-of-integers) – Warren Weckesser Mar 30 '15 at 10:59

3 Answers3

3

Another approach is using packbits from numpy. For this, however, numpy will fill with zeros the columns, until they get byte shape (length % 8). In order to avoid numpy from filling with 0's, we could add zeros at the beginning (to not change the binary value of the array).

Using the data from @Oliver W.

>>> import numpy as np
>>> b = np.random.random_integers(0,1,(3,5))
>>> b
array([[0, 1, 1, 1, 0],
       [1, 0, 1, 0, 1],
       [0, 1, 0, 0, 1]])
# Fill the begining with zeros to form bytes
>>> diff = 8 - b.shape[1] % 8
>>> if diff > 0: b = np.c_[np.zeros((b.shape[0], diff), int), b]
>>> b
array([[0, 0, 0, 0, 1, 1, 1, 0],
       [0, 0, 0, 1, 0, 1, 0, 1],
       [0, 0, 0, 0, 1, 0, 0, 1]])
# Get the integer number
>>> p = np.packbits(b, axis=1)
>>> p
array([[14],
       [21],
       [ 9]], dtype=uint8)
Imanol Luengo
  • 15,366
  • 2
  • 49
  • 67
  • Works (+1), but be warned: it only works as intended for values <256, because it packs the data in 8 bits. So if you have more columns than 8, you'll get back several columns rather than `Mx1`. – Oliver W. Mar 30 '15 at 09:51
  • Ops, thank you for that @Oliver W., I didn't know it. I guess if the columns have some sort of structure (i.e. represent a 8, 16, 32, 64 or 128 bits integers) it could be fixed by adding `p.view('u4')` (for a 32 bit integer, similar for others). It would return a new view for the columns – Imanol Luengo Mar 30 '15 at 10:05
1

You could multiply each element of the row with its corresponding multiplication factor 2**exponent where the exponent depends on the position of the digit within the row (this works for any positional number system by the way, such as base-60 and hexadecimal):

>>> import numpy as np
>>> 
>>> b = np.random.random_integers(0,1,(3,5))  # example array
>>> b
array([[0, 1, 1, 1, 0],
       [1, 0, 1, 0, 1],
       [0, 1, 0, 0, 1]])
>>> c = 2**np.arange(b.shape[1])[::-1] # reverse order: assumes the last column corresponds with the decimal number 1
>>> b.dot(c) # matrix multiplication
array([14, 21,  9])

Same result if you have instances of numpy's matrix class.

Oliver W.
  • 13,169
  • 3
  • 37
  • 50
0

You can join all 0s and 1s of every row as strings and from there it's easy to get the integer representation. I had to convert the matrix to an array to get this to work, but maybe there is a straight solution:

import numpy as np
A = np.matrix([[0, 1, 1, 1, 0],
               [1, 0, 1, 0, 1],
               [0, 1, 0, 0, 1]])

B = np.asarray(A)
#join all 0/1s together as string and convert to integer
C = np.matrix([int(''.join(str(x) for x in column),2) for column in B]).reshape((B.shape[0],1))

print C
>>>
[[14]
 [21]
 [ 9]]
igavriil
  • 1,001
  • 2
  • 12
  • 18