Numpy:使用字典作为地图有效地替换2D数组中的值

Ale*_*lex 9 python arrays dictionary numpy

我有一个2D Numpy整数数组,如下所示:

a = np.array([[  3,   0,   2,  -1],
              [  1, 255,   1,   2],
              [  0,   3,   2,   2]])
Run Code Online (Sandbox Code Playgroud)

我有一个字典,其中包含整数键和值,我想用它来替换a新值的值.该字典可能如下所示:

d = {0: 1, 1: 2, 2: 3, 3: 4, -1: 0, 255: 0}
Run Code Online (Sandbox Code Playgroud)

我想用a键入的值替换匹配的dd.换句话说,d定义旧(当前)和新(期望)值之间的映射a.以上玩具示例的结果如下:

a_new = np.array([[  4,   1,   3,   0],
                  [  2,   0,   2,   3],
                  [  1,   4,   3,   3]])
Run Code Online (Sandbox Code Playgroud)

实现这一目标的有效方法是什么?

这是一个玩具示例,但实际上数组会很大,它的形状将是例如(1024, 2048),字典将具有数十个元素的顺序(在我的情况下为34),而键是整数,它们不是必然都是连续的,它们可以是负数(如上例所示).

我需要在数十万个这样的阵列上执行此替换,因此需要快速.然而,字典是事先已知的并且保持不变,因此渐近地,任何用于修改字典或将其转换为更合适的数据结构的时间都无关紧要.

我正在循环遍历两个嵌套for循环中的数组条目(在行和列上a),但必须有一个更好的方法.

如果地图不包含负值(例如,在示例中为-1),我只会在字典中创建一个列表或数组,其中键是数组索引,然后将其用于有效的Numpy花式索引例程.但由于也存在负面价值,因此无效.

wwi*_*wii 5

制作数组的副本,然后迭代字典项,然后使用布尔索引将新值分配给副本。

import numpy as np
b = np.copy(a)
for old, new in d.items():
    b[a == old] = new
Run Code Online (Sandbox Code Playgroud)


And*_*den 5

这是一种方法,如果您有一个小字典/最小值和最大值,这可能会更有效,您可以通过添加数组 min 来解决负索引:

In [11]: indexer = np.array([d.get(i, -1) for i in range(a.min(), a.max() + 1)])

In [12]: indexer[(a - a.min())]
Out[12]:
array([[4, 1, 3, 0],
       [2, 0, 2, 3],
       [1, 4, 3, 3]])
Run Code Online (Sandbox Code Playgroud)

注意:这会将 for 循环移至查找表,但如果它明显小于实际数组,则速度可能会快得多。

  • 在我的例子中,这是最好的方法:由于字典保持不变并且所有可能的数组值都是预先知道的,因此索引器只需要创建一次,然后就可以用于处理大量数组。如果索引器只需要创建一次,这个方法大约比@wwii提出的方法快6倍。如果需要为每个要处理的数组重新创建索引器,那么我想它不会更快。 (2认同)