I have a large numpy array of signed bytes (dtype int8
). It contains values in the full range -128 to +127. I'd like to convert the efficiently to an array of unsigned bytes (dtype uint8
) by adding 128 to each element, such that -128 → 0, 0 → 128, +127 → 255, etc. so of course the results still fit into an unsigned byte.
Simple elementwise addition given the correct numerical result, but creates a result array using twice the memory (dtype int16
) in addition to the source array, even though only the low bytes of the result elements are needed.
>>> import numpy
>>> a = numpy.array( [-128, -1, 0, 1, 127 ], dtype=numpy.int8)
>>> b = a + 128
>>> b
array([ 0, 127, 128, 129, 255], dtype=int16)
Is there a way to control the dtype
of the result array to be uint8
?
The alternative approach of modifying the values in-place and "casting" the data to a new type, like this:
>>> for i in xrange(0, 5):
... if a[i] < 0:
... a[i] -= 128
... elif a[i] >= 0:
... a[i] += 128
...
>>> a
array([ 0, 127, -128, -127, -1], dtype=int8)
>>> a.view(dtype=numpy.uint8)
array([ 0, 127, 128, 129, 255], dtype=uint8)
is much more space efficient but very costly in time for large arrays with the transformation in Python.
How can I do this transformation in-place and quickly?
import numpy as np a = np.array([-128, -1, 0, 1, 127], dtype=np.int8) a = a.view(np.uint8) a += 128 print a # -> array([ 0, 127, 128, 129, 255], dtype=uint8)
This creates no copies, and all operations are in-place.
EDIT: safer to cast first to uint --- unsigned wrap-around is defined. EDIT2: s/numpy/np/g;
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