Python NumPy — срез трехмерного массива под углом

Работая в NumPy, я понимаю, как нарезать 2D-массивы из 3D-массива, используя эта статья.

В зависимости от оси, которую я хотел бы разрезать:

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 25 26]]]

Нарезка даст мне:

i_slice = array[0]

    [[0  1  2]
     [3  4  5]
     [6  7  8]]

j_slice = array[:, 0]

    [[0  1  2]
     [9  10 11]
     [18 19 20]]

k_slice = array[:, :, 0]

    [[0  3  6]
     [9  12 15]
     [18 21 24]]

Но можно ли разрезать под углом 45 градусов? например:

j_slice_down = array[slice going down starting from index 0]

    [[0  1  2]
     [12 13 14]
     [24 25 26]]

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

Обновление, выбранный ответ:

Я выбрал ответ hpaulj, создав два массива координат с помощью np.arrange. Немного поработав, я смог сделать так, чтобы он соответствовал моим потребностям: возвращать срез под любым углом, по любой оси, асимметричному измерению трехмерного массива и в любом положении, включая обертывание по всему периметру, чтобы это было одно и то же измерение. как ось.

Мой метод с использованием np.arrange

Два массива np.arrange были сделаны для x и y.

Различные методы, такие как np.roll, приращение, np.hstack и np.concatenate, были выполнены для массива оси x массива np.arrange. y = y[::-1] для альтернативного угла.

if axis is 'z': #i
    slice_notation = np.index_exp[x, y, :] 

elif axis is 'y': #k
    slice_notation = np.index_exp[x, :, y]

else: #j 
    slice_notation = np.index_exp[:, x, y]

Создает выражение среза, затем я использую slice_notation для выполнения необходимых операций на месте.

Другие предложенные методы: np.diagonal и np.eye могут быть более подходящими для других, поскольку у них могут быть другие требования, чем у меня.


person Enger Bewza    schedule 18.02.2019    source источник
comment
a[np.eye(len(a),dtype=bool)] с a в качестве входного массива?   -  person Divakar    schedule 18.02.2019
comment
Вау.. @Divakar! Это дает мне результат примера. Позвольте мне подробнее изучить np.eye. Благодарю вас!   -  person Enger Bewza    schedule 18.02.2019
comment
Другой с einsum должен быть более эффективным: np.einsum('iij->ij',a).   -  person Divakar    schedule 18.02.2019


Ответы (2)


Вы можете попробовать с np.diagonal:

arr = np.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 ,25 ,26]]])

np.diagonal(arr).T
array([[ 0,  1,  2],
       [12, 13, 14],
       [24, 25, 26]])
person Chris    schedule 18.02.2019
comment
np.diagonal имеет оси1 и оси2 как kwargs. Они позволяют вам выбрать, какой диагональный фрагмент arr будет возвращен. - person Tls Chris; 18.02.2019

person    schedule
comment
Хотя этот код может дать ответ на вопрос, предоставление дополнительного контекста относительно того, как и/или почему он решает проблему, улучшит долгосрочную ценность ответа. - person Vasilisa; 18.02.2019
comment
для небольших диапазонов срезов мне нравится этот порядок, так как вы можете упорядочить нарезку в соответствии с расширением … например. a[[0,1,2],[0,1,2],:] или … a[[2,1,0],[0,1,2],:] - person NaN; 18.02.2019
comment
@hpaulj - Кажется, это то, что я ищу. Итак, я могу применить это ко всем осям, поместив np.arange в другие места, чем ваш пример. Кроме того, изменение вывода np.arange позволяет мне выбирать в другом направлении, а начиная с отрицательных значений позволяет мне создавать выборки обертывания. - person Enger Bewza; 19.02.2019
comment
Это наиболее полезно для моего использования, так как я хотел бы выполнять действия над 3D-массивом с помощью среза вместо извлечения среза из массива. Я поиграю немного дальше, и если это удастся, я приведу несколько примеров и приму этот ответ. - person Enger Bewza; 19.02.2019
comment
np.where(np.eye(3)) производит те же два диапазона, поэтому мой ответ связан с комментарием eye @Divakar. - person hpaulj; 19.02.2019