I need to pack a numpy 2D array with struct.pack, and I'm seeking a method which can do this in a batch. I tried:
X = numpy.array([[1,2,3],[4,5,6]])
b = struct.pack('=%sf' % X.size, *X)
but this doesn't work. It prompts:
struct.error: pack expected 6 items for packing (got 2)
Is there a better way to pack the NumPy array instead of looping over each element?
array(a) . List append is faster than array append .
Numpy data structures perform better in: Size - Numpy data structures take up less space. Performance - they have a need for speed and are faster than lists. Functionality - SciPy and NumPy have optimized functions such as linear algebra operations built in.
In general it is better/faster to iterate or append with lists, and apply the np. array (or concatenate) just once. appending to a list is fast; much faster than making a new array.
If we want to bind or zip the data of different array then we can go for zip function in python of NumPy. This function eliminates the need of class object if not required. We can easily map our data with any number of the array and this can be done very easily with the use of the zip() function.
If you have a numpy array, you already have your data packed in memory, you don't need to use struct
:
>>> a = np.arange(1, 7)
>>> struct.pack('=6f', *a)
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@\x00\x00\xa0@\x00\x00\xc0@'
>>> a.astype('f').tostring()
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@\x00\x00\xa0@\x00\x00\xc0@'
And if your array is multidimensional, .tostring
takes a flattened view by default:
>>> a = np.arange(1, 7).reshape(2, 3)
>>> a.astype('f').tostring()
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@\x00\x00\xa0@\x00\x00\xc0@'
Seemed the '*' operator combined with struct.pack only works with 1D array. So for ND array, it has to be flattened to 1D firstly.
X = numpy.array([[1,2,3],[4,5,6]])
b = struct.pack('=%sf' % X.size, *X.flatten('F'))
This works for me.
The *
acts like an iterator. Iterating on an 2d array returns the rows of that array. For example:
In [9]: def foo(*args):
print(args)
In [10]: foo(*np.ones((2,3)))
(array([ 1., 1., 1.]), array([ 1., 1., 1.]))
args
, inside the function, is 2 tuples, each a row of the array. That is why your pack
got 2 items, rather than 6 (x.size
). When you flatten the array, *
produces all 6 items.
In [11]: foo(*np.ones((2,3)).flat)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
But what's the purpose of this pack
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With