2017-01-06 1 views
3
x = [[1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9]] 

Вращение на 1 единицу должно дать:Как вы поворачиваете элементы в массиве 2D numpy с помощью единиц 'n'?

x = [[4, 1, 2], 
    [7, 5, 3], 
    [8, 9, 6]] 

В принципе, я хочу, чтобы сдвинуть каждый круговой слой в массиве с помощью единиц «N».

Я посмотрел на numpy.roll, но не мог понять, использовать его для этого прецедента. Я не могу использовать процедуры вращения изображения, такие как scipy.ndimage.interpolation.rotate, поскольку они меняют форму и не совсем достигают желаемого результата.

Редактировать:

Для матрицы 4 х 4:

x = [[a, b, c, d], 
    [e, f, g, h], 
    [i, j, k, l], 
    [m, n, o, p]] 

Вращение на 1 единицу должно дать:

x = [[e, a, b, c], 
    [i, j, f, d], 
    [m, k, g, h], 
    [n, o, p, l]] 

Редактировать:

Добавление некоторых clarificati как это работает для произвольных размеров.

Для матрицы N X N, повернутой на 1 единицу, внешнее «кольцо» сначала сдвигается на 1. Та же логика рекурсивно следит за оставшейся внутренней матрицей (N-2) X (N-2).

+2

Я не знаком с numpy, но должен ли массив * rotation * влиять на элементы внутри него? Поскольку у вас есть 9 в исходном массиве, но не во вращающейся версии. Я искренне не уверен, просто спрашиваю, если это может быть ошибкой. – Tagc

+2

Не могли бы вы показать образец для массива 4x4? – Divakar

+0

Можете ли вы проверить свой результат? Предполагается, что это '[[4, 1, 2], [7, 5, 3], [8, 9, 6]]'? Потому что прямо сейчас я не могу понять это ... – Praveen

ответ

2

Вот такой подход, предполагающий, что вы хотите повернуть так, чтобы величина сдвига была постоянной на срезах, где срезом мы имеем в виду внешний слой элементов, направленный наружу от центра -

def outer_slice(x): 
    return np.r_[x[0],x[1:-1,-1],x[-1,:0:-1],x[-1:0:-1,0]] 

def rotate_steps(x, shift): 
    out = np.empty_like(x) 
    N = x.shape[0] 
    idx = np.arange(x.size).reshape(x.shape) 
    for n in range((N+1)//2): 
     sliced_idx = outer_slice(idx[n:N-n,n:N-n]) 
     out.ravel()[sliced_idx] = np.roll(np.take(x,sliced_idx), shift) 
    return out 

Sample работает

Дело № 1 (3 х 3 массив):

In [444]: x 
Out[444]: 
array([[24, 85, 97], 
     [51, 33, 11], 
     [86, 38, 33]]) 

In [445]: rotate_steps(x,shift=1) 
Out[445]: 
array([[51, 24, 85], 
     [86, 33, 97], 
     [38, 33, 11]]) 

Корпус № 2 (массив 4 х 4):

In [447]: x 
Out[447]: 
array([[11, 70, 28, 13], 
     [44, 41, 17, 82], 
     [47, 32, 89, 25], 
     [32, 20, 67, 98]]) 

In [448]: rotate_steps(x,shift=1) 
Out[448]: 
array([[44, 11, 70, 28], 
     [47, 32, 41, 13], 
     [32, 89, 17, 82], 
     [20, 67, 98, 25]]) 

In [449]: rotate_steps(x,shift=2) 
Out[449]: 
array([[47, 44, 11, 70], 
     [32, 89, 32, 28], 
     [20, 17, 41, 13], 
     [67, 98, 25, 82]]) 
+0

Спасибо. Это выполняет свою работу. – ragha

1

Для матрицы 3х3, вы можете сделать это с np.roll и ndarray.flat:

>>> x = np.arange(1, 10).reshape((3, 3)) 
>>> x 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 
>>> i = np.array([0, 1, 2, 5, 8, 7, 6, 3]) # Indices in circular order 
>>> x.flat[i] 
array([1, 2, 3, 6, 9, 8, 7, 4]) 

Поворот на 1 единицу продукции:

>>> x.flat[i] = np.roll(x.flat[i], 1) # Rotate indices and reassign 
>>> x 
array([[4, 1, 2], 
     [7, 5, 3], 
     [8, 9, 6]]) 

Поворот на 4 единицы:

>>> x.flat[i] = np.roll(x.flat[i], 4) 
>>> x 
array([[9, 8, 7], 
     [6, 5, 4], 
     [3, 2, 1]]) 

Для в случае с 4x4, мне все еще нужна определенная ясность в отношении того, нужно ли поворачивать каждый «круг» разные «скорости» в соответствии с их длиной ...

+0

Это интересный подход. – ragha

1

Вы применяете перестановку на матрицу. Перестановки обычно представлены векторами (i -> p [i]) и применяются на векторах. Вы можете представить перестановку матрицы в матрице, если хотите, перестановка будет матрицей пар, так что элемент at (i, j) перемещается в m [i, j].

Как только вы построите матрицу, это просто вопрос простой петли, чтобы применить перестановку.

+0

Я считаю, что это была идея @Praveen. – ragha

Смежные вопросы