У меня есть (5, 5) 2D-массив Numpy:
map_height = 5
map_width = 5
# Define a 2D np array-
a = np.arange(map_height * map_width).reshape(map_height, map_width)
# a
'''
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
'''
Я могу обернуть этот массив по обеим осям, используя «pad()»:
a_wrapped = np.pad(array = a, pad_width = 1, mode = 'wrap')
a_wrapped
'''
array([[24, 20, 21, 22, 23, 24, 20],
[ 4, 0, 1, 2, 3, 4, 0],
[ 9, 5, 6, 7, 8, 9, 5],
[14, 10, 11, 12, 13, 14, 10],
[19, 15, 16, 17, 18, 19, 15],
[24, 20, 21, 22, 23, 24, 20],
[ 4, 0, 1, 2, 3, 4, 0]])
'''
Двумерные координаты (5, 5) «a» вычисляются (неэффективно) как:
# 2D coordinates -
# 1st channel/axis = row indices & 2 channel/axis = column indices.
a_2d_coords = np.zeros((map_height, map_width, 2), dtype = np.int16)
for row_idx in range(map_height):
for col_idx in range(map_width):
a_2d_coords[row_idx, col_idx][0] = row_idx
a_2d_coords[row_idx, col_idx][1] = col_idx
# a_2d_coords.shape
# (5, 5, 2)
Я также хочу обернуть этот массив 2D-координат «a_2d_coords», выполнив:
a_2d_coords_wrapped = np.pad(array = a_2d_coords, pad_width = 1, mode = 'wrap')
# a_2d_coords_wrapped.shape
# (7, 7, 4)
Он также оборачивает третью ось/измерение, чего делать не следует! Цель состоит в том, чтобы координаты a[1, 4] = (1, 4) и координаты его соседа справа (RHS) были a[1, 0] = (1, 0). Это обтекание оси X. Аналогично, 2D-координаты оси Y также должны быть перенесены.






Прежде всего, вы можете упростить расчет 2D-координат следующим образом:
a_2d_coords = np.moveaxis(np.mgrid[:map_height, :map_width], 0, -1)
Давайте проверим, дает ли это тот же результат:
import numpy as np
# For the check, use different height and width values to detect swaps
map_height, map_width = 3, 7
# Original implementation for coords
a_2d_coords_given = np.zeros((map_height, map_width, 2), dtype = np.int16)
for row_idx in range(map_height):
for col_idx in range(map_width):
a_2d_coords_given[row_idx, col_idx][0] = row_idx
a_2d_coords_given[row_idx, col_idx][1] = col_idx
# Proposed implementation for coords
a_2d_coords = np.moveaxis(np.mgrid[:map_height, :map_width], 0, -1)
# Equality check
assert np.all(a_2d_coords == a_2d_coords_given)
Во-вторых, если вы заметите, что аргумент pad_widthnp.pad также может принимать значения, специфичные для оси, то вы можете добиться желаемого заполнения координат следующим образом:
a_2d_coords_wrapped = np.pad(a_2d_coords, mode = "wrap",
pad_width=((1, 1), (1, 1), (0, 0)))
Теперь мы дополняем ось 0 и ось 1 одним ведущим и одним конечным значением ((1, 1)), но оставляем ось 2 в покое ((0, 0)).
Итого имеем:
import numpy as np
map_height, map_width = 5, 5
a = np.arange(map_height * map_width).reshape(map_height, map_width)
a_2d_coords = np.moveaxis(np.mgrid[:map_height, :map_width], 0, -1)
a_2d_coords_wrapped = np.pad(a_2d_coords, mode = "wrap",
pad_width=((1, 1), (1, 1), (0, 0)))
print(a[a_2d_coords_wrapped[..., 0], a_2d_coords_wrapped[..., 1]])
# Prints
# [[24 20 21 22 23 24 20]
# [ 4 0 1 2 3 4 0]
# [ 9 5 6 7 8 9 5]
# [14 10 11 12 13 14 10]
# [19 15 16 17 18 19 15]
# [24 20 21 22 23 24 20]
# [ 4 0 1 2 3 4 0]]
Мы можем упростить код еще на один шаг, предоставив a_2d_coords/a_2d_coords_wrapped как массив 2×В×Ш, а не массив В×Ш×2:
import numpy as np
map_height, map_width = 5, 5
a = np.arange(map_height * map_width).reshape(map_height, map_width)
a_2d_coords = np.mgrid[:map_height, :map_width]
a_2d_coords_wrapped = np.pad(a_2d_coords, mode = "wrap",
pad_width=((0, 0), (1, 1), (1, 1)))
print(a[*a_2d_coords_wrapped])
# Prints
# [[24 20 21 22 23 24 20]
# [ 4 0 1 2 3 4 0]
# [ 9 5 6 7 8 9 5]
# [14 10 11 12 13 14 10]
# [19 15 16 17 18 19 15]
# [24 20 21 22 23 24 20]
# [ 4 0 1 2 3 4 0]]
Обратите внимание на * в a[*a_2d_coords_wrapped], который необходим для «распаковки» координат, чтобы для индексации предоставлялись два массива H×W, а не один массив 2×H×W.
a[*a_2d_coords_wrapped] выдает ошибку: a[*a_2d_coords_wrapped] — SyntaxError: неверный синтаксис
@Arun (1) Какую версию Python вы используете? Используемый синтаксис, возможно, работает только для более поздних версий Python. (2) Вместо этого в любом случае должно работать следующее: a[a_2d_coords_wrapped[0], a_2d_coords_wrapped[1]]
Мне не очень понятно, чего вы ожидаете в результате. Не могли бы вы добавить пример для этой части? Какова окончательная форма?