python - Type casting error with numpy.take -
i have look-up table (lut) stores 65536 uint8
values:
lut = np.random.randint(256, size=(65536,)).astype('uint8')
i want utilize lut convert values in array of uint16
s:
arr = np.random.randint(65536, size=(1000, 1000)).astype('uint16')
and want conversion in place, because lastly array can pretty big. when seek it, next happens:
>>> np.take(lut, arr, out=arr) traceback (most recent phone call last): file "<stdin>", line 1, in <module> file "c:\python27\lib\site-packages\numpy\core\fromnumeric.py", line 103, in take homecoming take(indices, axis, out, mode) typeerror: array cannot safely cast required type
and don't understand going on. know that, without out
argument, homecoming of same dtype lut
, uint8
. why can't uint8
cast uint16
? if inquire numpy:
>>> np.can_cast('uint8', 'uint16') true
obviously next works:
>>> lut = lut.astype('uint16') >>> np.take(lut, arr, out=arr) array([[173, 251, 218, ..., 110, 98, 235], [200, 231, 91, ..., 158, 100, 88], [ 13, 227, 223, ..., 94, 56, 36], ..., [ 28, 198, 80, ..., 60, 87, 118], [156, 46, 118, ..., 212, 198, 218], [203, 97, 245, ..., 3, 191, 173]], dtype=uint16)
but works:
>>> lut = lut.astype('int32') >>> np.take(lut, arr, out=arr) array([[ 78, 249, 148, ..., 77, 12, 167], [138, 5, 206, ..., 31, 43, 244], [ 29, 134, 131, ..., 100, 107, 1], ..., [109, 166, 14, ..., 64, 95, 102], [152, 169, 102, ..., 240, 166, 148], [ 47, 14, 129, ..., 237, 11, 78]], dtype=uint16)
this makes no sense, since int32
s beingness cast uint16
s, not safe thing do:
>>> np.can_cast('int32', 'uint16') false
my code works if set lut
's dtype in uint16
, uint32
, uint64
, int32
or int64
, fails uint8
, int8
, int16
.
am missing something, or broken in numpy?
workarounds welcome... since lut not big, guess not bad have type match array's, if takes twice space, doesn't sense right that...
is there way tell numpy not worry casting safety?
interesting problem. numpy.take(lut, ...)
gets transformed lut.take(...)
source can looked @ here:
https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/item_selection.c#l28
i believe exception thrown at line 105:
obj = (pyarrayobject *)pyarray_fromarray(out, dtype, flags); if (obj == null) { goto fail; }
where in case out
arr
dtype
1 of lut
, i.e. uint8
. tries cast arr
uint8
, fails. have i'm not sure why needs that, pointing out does... reason take
seems assume want output array have same dtype
lut
.
by way, in many cases phone call pyarray_fromarray
create new array , replacement not in place. case illustration if phone call take
mode='raise'
(the default, , happens in examples), or whenever lut.dtype != arr.dtype
. well, @ to the lowest degree should, , can't explain why, when cast lut
int32
output array remains uint16
! mystery me - maybe has npy_array_updateifcopy flag (see here).
bottom line:
the behavior of numpy indeed hard understand... maybe else provide insight why does i not seek processarr
in place - seems new array created under hood in cases anyway. i'd go arr = lut.take(arr)
- way free half of memory used arr
. python numpy lookup-tables
No comments:
Post a Comment