Переместить элемент в массиве по очереди и сдвинуть остальные? - PullRequest
0 голосов
/ 28 февраля 2020

Я работаю с массивами numpy, и я хотел бы переместить определенное значение, расположенное по определенному индексу, на 2 позиции справа, при этом сдвигая другие элементы, задействованные слева, на одну позицию каждый. Если быть более точным, то вот что я хотел бы достичь:

от:

     start = [0., 1., 2.],
             [0., 0., 0.],
             [5., 0., 1.]

до:

       end = [1., 2., 0.],
             [0., 0., 0.],
             [5., 0., 1.]

Как видно из первого ряд, 0 был перемещен на две позиции справа и 1 и 2 на одну позицию слева. До сих пор мне удавалось переместить элемент на одну позицию, а другую - определить:

def right_move(arr, index, n_steps:int):


   row = index[0]
   col = index[1]

   try:
       arr[row,col], arr[row, col + n_steps] = arr[row, col + n_steps], arr[row, col]

   except:
       pass

   return arr

, где n_steps = 1. Если я введу n_steps = 2, он не будет работать, так как элемент в середине перестановки остается неизменным.

Может кто-нибудь мне помочь? Другие более простые решения приветствуются!

Спасибо

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Вы можете использовать numpy.roll:

import numpy as np

arr = np.array([[0., 1., 2.],
                [0., 0., 0.],
                [5., 0., 1.]])
arr[0] = np.roll(arr[0], 2)
arr
# output:
# [[1., 2., 0.],
#  [0., 0., 0.],
#  [5., 0., 1.]]
0 голосов
/ 29 февраля 2020

Предполагается функциональность np.roll. Тем не менее, np.roll не разрешает бросок в отдельном ряду. Это вызвало у меня интерес к реализации функции, использующей as_strided, чтобы расширить эту функциональность до np.roll

from numpy.lib.stride_tricks import as_strided

def custom_roll(arr, r_tup):
    m = np.asarray(r_tup)
    arr_roll = arr[:, [*range(arr.shape[1]),*range(arr.shape[1]-1)]].copy() #need `copy`
    strd_0, strd_1 = arr_roll.strides
    n = arr.shape[1]
    result = as_strided(arr_roll, (*arr.shape, n), (strd_0 ,strd_1, strd_1))

    return result[np.arange(arr.shape[0]), (n-m)%n]

. Просто передавая кортеж, укажите количество шагов для каждой строки. В вашем случае, он катит только строку 0 или 2 позиции вперед или -1 позицию назад. Таким образом, кортеж будет (2,0,0) или (-1,0,0)

start = np.array([[0., 1., 2.],
                  [0., 0., 0.],
                  [5., 0., 1.])

out = custom_roll(start, (2,0,0))

Out[780]:
array([[1., 2., 0.],
       [0., 0., 0.],
       [5., 0., 1.]])

Или

out = custom_roll(start, (-1,0,0))

Out[782]:
array([[1., 2., 0.],
       [0., 0., 0.],
       [5., 0., 1.]])

Бросьте первую и последнюю строку: (2,0,2)

out =  custom_roll(start, (2,0,2))

Out[784]:
array([[1., 2., 0.],
       [0., 0., 0.],
       [0., 1., 5.]])
...