Преобразование 2d массива NumPy в 3d с повторяющимися строками - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть массив NumPy следующим образом:

arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])

Я хочу устроить так, чтобы он выглядел так:

[[[6,7,8,9,10],
  [1,2,3,4,5]],
 [[11,12,13,14,15],
  [6,7,8,9,10]],
 [[16,17,18,19,20],
  [11,12,13,14,15]]]

Так что, по сути, 3D-массив с 2x5 в каждомстрока массива.Код, который я пробовал:

x=np.zeros([3,2,5])
for i in range(len(arr)):
    x[i]=arr[i:i+2,:][::-1]

Но это приводит к выводу ниже:

[[[ 6.  7.  8.  9. 10.]
  [ 1.  2.  3.  4.  5.]]    
 [[ 0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.]]  
 [[ 0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.]]]

[[[ 6.  7.  8.  9. 10.]
  [ 1.  2.  3.  4.  5.]]    
 [[11. 12. 13. 14. 15.]
  [ 6.  7.  8.  9. 10.]]    
 [[ 0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.]]]

[[[ 6.  7.  8.  9. 10.]
  [ 1.  2.  3.  4.  5.]]    
 [[11. 12. 13. 14. 15.]
  [ 6.  7.  8.  9. 10.]]    
 [[16. 17. 18. 19. 20.]
  [11. 12. 13. 14. 15.]]]

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

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

import numpy as np 
arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]]) 

# compute the strides and shape of the output array
in_strides = arr.strides 
out_strides = in_strides[:1] + in_strides 
out_shape = (3, 2) + arr.shape[-1:]  # keep the last dimension's size
strided = np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
out_arr = strided[:, ::-1, :].copy()  # use a copy to stay safe

Выше будет безопасно работать до тех пор, пока out_shape[-1] <= arr.shape[1] иsum(out_shape[:2]) <= arr.shape[0] + 1.Это ограничения, которые делают скользящее окно значимым внутри исходного массива, и ваш фактический вариант использования, естественно, должен их учитывать.

Важные примечания:

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

    >>> out_strides = in_strides[:1] + in_strides 
    ... out_shape = (3, 3, 5)  # 3 + 3 == 6 > arr.shape[0] + 1 == 5
    ... np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
    array([[[         1,              2,              3,              4,
                      5],
        [             6,              7,              8,              9,
                     10],
        [            11,             12,             13,             14,
                     15]],
    
       [[             6,              7,              8,              9,
                     10],
        [            11,             12,             13,             14,
                     15],
        [            16,             17,             18,             19,
                     20]],
    
       [[            11,             12,             13,             14,
                     15],
        [            16,             17,             18,             19,
                     20],
        [           384,            193, 94379169559968,              0,
                      0]]])
    
  • Если вы не будете изменять свой массивпосле этого, и только потом, вы можете опустить последний .copy() вызов в вышеприведенном.Это даст вам расширенный массив, который разделяет память с исходным массивом, но, что более важно, строки массива будут совместно использовать память друг с другом.Это не , что вы обычно хотите, но если ваш реальный массив очень большой и , вы знаете, что можете смело предполагать, что значения не будут независимо изменяться, объем памяти может иметь значение,Еще один аспект, который следует учитывать, заключается в том, что вызов .copy() для результата даст вам непрерывный блок памяти, что, вероятно, лучше для производительности в будущем, в зависимости от того, что вы планируете делать с результирующим массивом.
0 голосов
/ 02 февраля 2019

Мы можем использовать np.lib.stride_tricks.as_strided на основе scikit-image's view_as_windows, чтобы получить раздвижные окна. Дополнительная информация об использовании as_strided на основе view_as_windows.

from skimage.util.shape import view_as_windows

x = view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]

Это просто будет представление входного массива.Следовательно, нет никаких дополнительных затрат памяти и практически свободного времени выполнения.Если вы хотите вывод с собственным пространством памяти, добавьте туда .copy(), то есть x.copy().

Пример выполнения -

In [15]: from skimage.util.shape import view_as_windows

In [16]: view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
Out[16]: 
array([[[ 6,  7,  8,  9, 10],
        [ 1,  2,  3,  4,  5]],

       [[11, 12, 13, 14, 15],
        [ 6,  7,  8,  9, 10]],

       [[16, 17, 18, 19, 20],
        [11, 12, 13, 14, 15]]])
0 голосов
/ 02 февраля 2019

Нет необходимости использовать какие-либо петли.Достаточно нарезки:

x = np.zeros([3,2,5], dtype=int)
x[:,0] = arr[-3:,:]
x[:,1] = arr[:3,:]

По существу вы назначаете 0-ую строку на всех страницах последним 3 строкам arr, а 1-ую строку на всех страницах первым 3 строкам arr.

...