Проблема
У меня есть двумерный массив NumPy, arr
, и для каждой строки я хотел бы обратить вспять часть массива. Важно отметить, что для каждой строки индексы start
и stop
должны быть уникальными. Я могу добиться этого, используя следующее.
import numpy as np
arr = np.repeat(np.arange(10)[np.newaxis, :], 3, axis=0)
reverse = np.sort(np.random.choice(arr.shape[1], [arr.shape[0], 2], False))
# arr
# array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
# reverse
# array([[1, 7],
# [8, 9],
# [4, 6]])
Переверните каждую строку между индексами start
, stop
в обратном порядке.
for idx, (i, j) in enumerate(reverse):
arr[idx, i:j+1] = arr[idx, i:j+1][::-1]
# arr
# array([[0, 7, 6, 5, 4, 3, 2, 1, 8, 9],
# [0, 1, 2, 3, 4, 5, 6, 7, 9, 8],
# [0, 1, 2, 3, 6, 5, 4, 7, 8, 9]])
Вопрос
Возможно ли это с помощью c нарезка и индексация? Я попытался использовать вывод reverse
для формирования нескольких slice
объектов, но безуспешно.
Обновление
Простое сравнение исходного метода с ответом. По моим данным, решение требуется только для работы с 2D матрицами с формой (50, 100).
import numpy as np
def reverse_one(arr, n):
temp = np.repeat(arr.copy(), n, axis=0)
reverse = np.sort(np.random.choice(temp.shape[1], [n, 2], False))
for idx, (i, j) in enumerate(reverse):
temp[idx, i:j+1] = temp[idx, i:j+1][::-1]
return temp
def reverse_two(arr, n):
temp = np.repeat(arr.copy(), n, axis=0)
reverse = np.sort(np.random.choice(temp.shape[1], [n, 2], False))
rev = np.ravel_multi_index((np.arange(n)[:, np.newaxis], reverse), temp.shape)
rev[:, 1] += 1
idx = np.arange(temp.size).reshape(temp.shape)
s = np.searchsorted(rev.ravel(), idx, 'right')
m = (s % 2 == 1)
g = rev[s[m] // 2]
idx[m] = g[:, 0] - (idx[m] - g[:, 1]) - 1
return temp.take(idx)
m = 100
arr = np.arange(m)[np.newaxis, :]
print("reverse_one:")
%timeit reverse_one(arr, m//2)
print("=" * 40)
print("reverse_two:")
%timeit reverse_two(arr, m//2)
Запуск следующего кода в блокноте Jupyter дает следующие результаты.
reverse_one:
1000 loops, best of 5: 202 µs per loop
========================================
reverse_two:
1000 loops, best of 5: 363 µs per loop