我有以下2D numpay数组:
matrix = np.array([
[ 0, 1, 4, 3],
[ 1, 2, 5, 4],
[ 3, 4, 7, 6],
[ 4, 5, 8, 7],
[ 2, 10, 13, 5],
[10, 11, 14, 13],
[ 5, 13, 16, 8],
[13, 14, 17, 16],
[18, 19, 22, 21],
[19, 11, 10, 22],
[21, 22, 1, 0],
[22, 10, 2, 1]])
我有另一个数组,它包含我想要替换的矩阵中的值。
substitutes = np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 13, 14, 16, 17, 18, 19, 21, 22])
查找矩阵中每个替换项的索引(可能多次出现):
indices = [np.argwhere(s == matrix) for s in substitutes]
然后我做:
matrix_renumbered = copy.deepcopy(matrix)
for i, indices_per_value in enumerate(indices):
for index in indices_per_value:
# the substitutes are replaced just by the counter i (to be contiguous)
matrix_renumbered[index[0], index[1]] = i
预期结果:
array([[ 0, 1, 4, 3],
[ 1, 2, 5, 4],
[ 3, 4, 7, 6],
[ 4, 5, 8, 7],
[ 2, 9, 11, 5],
[ 9, 10, 12, 11],
[ 5, 11, 13, 8],
[11, 12, 14, 13],
[15, 16, 18, 17],
[16, 10, 9, 18],
[17, 18, 1, 0],
[18, 9, 2, 1]])
是否有更好的方法(例如使用numpy)来做双for循环所做的事情?
安迪
您可以通过利用高级索引来删除内部for
循环:
for value, adv_idx in enumerate(tuple(zip(*i)) for i in indices):
matrix_renumbered[adv_idx] = value
输出:
array([[ 0, 1, 4, 3],
[ 1, 2, 5, 4],
[ 3, 4, 7, 6],
[ 4, 5, 8, 7],
[ 2, 9, 11, 5],
[ 9, 10, 12, 11],
[ 5, 11, 13, 8],
[11, 12, 14, 13],
[15, 16, 18, 17],
[16, 10, 9, 18],
[17, 18, 1, 0],
[18, 9, 2, 1]])
高级索引允许您传入行坐标列表和列坐标列表,并访问数组的这些元素:
In [1]: x = np.random.randint(0, 9, (5, 5))
In [2]: x
Out[2]:
array([[1, 2, 4, 0, 5],
[1, 5, 7, 4, 3],
[1, 3, 6, 8, 0],
[6, 3, 7, 6, 3],
[4, 3, 6, 8, 6]])
In [3]: x[[1, 2, 3], [0, 0, 0]] = 999
In [4]: x
Out[4]:
array([[ 1, 2, 4, 0, 5],
[999, 5, 7, 4, 3],
[999, 3, 6, 8, 0],
[999, 3, 7, 6, 3],
[ 4, 3, 6, 8, 6]])
在这里,您使用高级索引x[[1, 2, 3], [0, 0, 0]]
获取第1、2和3行以及第0、0和0列。
你唯一需要改变的是你的索引数组,你需要zip()
坐标成两个单独的列表,一个为行值和另一个列值(而不是(row, col)
对的序列),这是通过以下方式实现的:
tuple(zip(*idx)) for idx in indices