如何高效地将numpy.int8数组原地转换为值偏移的numpy.uint8数组?

9 投票
2 回答
14950 浏览
提问于 2025-04-17 04:01

我有一个很大的numpy数组,里面存的是带符号的字节(dtype int8)。这个数组的值范围是从-128到+127。我想把它高效地转换成一个无符号字节的数组(dtype uint8),方法是给每个元素加上128,这样-128就变成0,0变成128,+127变成255,等等。这样转换后,结果仍然可以放进无符号字节里。

简单地逐个加上128可以得到正确的数字结果,但这样会生成一个结果数组,它的内存使用量是原数组的两倍(dtype int16),虽然其实只需要结果元素的低字节。

>>> 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)

有没有办法让结果数组的dtype变成uint8呢?

另一种方法是直接在原数组上修改值,然后把数据“转换”成新类型,像这样:

>>> 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)

这种方法在空间上更高效,但对于大数组来说,转换的时间成本很高。

我该如何快速且在原地完成这个转换呢?

2 个回答

1
In [18]: a = numpy.array( [-128, -1, 0, 1, 127 ], dtype=numpy.int8)
In [19]: z = a.view(dtype=numpy.uint8)

In [20]: z += 128

In [21]: z
Out[21]: array([  0, 127, 128, 129, 255], dtype=uint8)

我希望我没有误解需求。

18
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)

这段代码不会创建任何副本,所有的操作都是在原地进行的。

补充说明: 首先转换为无符号整数(uint)会更安全,因为无符号整数的循环特性是有定义的。

补充说明2: 把“numpy”替换成“np”。

撰写回答