在Python 3中,将查找表应用于NUMPY数组的最有效方法是什么?

3
我正在尝试使用numpy数组尽可能提高性能。
我有一个查找表,比如说:MYLUT = [0,2,5,7,8,12,-1,...,229]
我有一个形状为(300,200000)、具有uint8值的numpy数组MYARRAY。
将查找表应用于MYARRAY中的所有元素的最快方法是什么?
目前,我只是使用for循环。
for i in range(300) :
    for j in range(200000) :
        MYARRAY[i][j] = MYLUT[MYARRAY[i][j]]

我能做得更好吗?或者这已经是在Python中完成此操作的最快方式了?
2个回答

10

NumPy可以非常高效地完成这个任务:

arr = np.array([[1,2,3],[0,0,1]])
lut = np.array([0,2,5,7,8,12])
print(lut.take(arr))

它给出:

array([[2, 5, 7],
       [0, 0, 2]])

请注意,这与lut[arr]的效果相同。此外,请注意应该注意您的数据类型-在您的示例数据中,LUT中有-1,但您说您的数据是无符号的。

如果您想要更高效,可以使用take()out参数:

lut.take(arr, out=arr)

这样就避免了创建新的数组,而且更接近于你原先的代码,可以直接在原始arr中进行更新。


1
lut.take( arr, mode="clip" ) 可以很有用; 默认值为 mode="raise" - denis

5

MYLUT[MYARRAY] 应该可以正常工作:


MYLUT = np.array([0,2,5,7,8,12,-1,229])
MYARRAY = np.random.randint(0,8,8).reshape(4,2)

MYARRAY
#array([[5, 4],
#       [7, 5],
#       [4, 3],
#       [1, 5]])

new_array = np.empty_like(MYARRAY)
for i in range(4) :
    for j in range(2) :
        new_array[i,j] = MYLUT[MYARRAY[i,j]]

new_array
#array([[ 12,   8],
#       [229,  12],
#       [  8,   7],
#       [  2,  12]])

MYLUT[MYARRAY]
#array([[ 12,   8],
#       [229,  12],
#       [  8,   7],
#       [  2,  12]])

这似乎比使用numpy.take更快。哦,对了,既然我在这里,如何创建一个形状为(100, 1000)且每行的每个元素都保持该行索引值的numpy数组,因此对于第0行,数组元素将是[0,0,...0](<-其中有1000个),最后一行将是[999,999,...999]。现在我只是使用列表推导来完成它,然后使用numpy.asarray()进行转换。 - bFig8
你可以使用 np.repeat(np.arange(100), 1000).reshape(100, 1000) 或者 np.broadcast_to(np.arange(100)[:,None], (100, 1000))。我猜你说的 999 实际上是指 99,因为总共只有 100 行。 - Psidom
1
不错!谢谢你!哦,是的,你说得对。应该是[99,99,...99]。 - bFig8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接