簡體   English   中英

構建和移動 numpy 陣列

[英]Building and shifting numpy array

我有這樣一個 numpy 數組:

在此處輸入圖像描述

我想用 N 移動這個數組,這樣我就可以得到一個新數組,這樣前 4 行將是開始數組的前 4 行,下面的行將是上一步的行。

我不知道如何正確解釋它,但看看我用 1 移動的例子(不是整個數組,但我想對整個數組這樣做):

在此處輸入圖像描述

當我用 2 移動時(不是整個數組,但我想對整個數組執行此操作):

在此處輸入圖像描述

如果我用 3 移動,我將在第一列有 12 個零,前面有 3 行..

這是代碼:

import numpy as np
import numpy 

def shift_one(arr):
  arrT = arr.transpose()
  arrT_shape = arrT.shape[0]

  col1 = arrT[:, [0]]
  prev1 = numpy.zeros([arrT_shape, 1])   
  x1 = numpy.vstack([col1, prev1])

  col2 = arrT[:, [1]]
  prev2 = arrT[:, [0]]
  x2 = numpy.vstack([col2, prev2])

  col3 = arrT[:, [2]]
  prev3 = arrT[:, [1]]
  x3 = numpy.vstack([col3, prev3])

  col4 = arrT[:, [3]]
  prev4 = arrT[:, [2]]
  x4 = numpy.vstack([col4, prev4])

  col5 = arrT[:, [4]]
  prev5 = arrT[:, [3]]
  x5 = numpy.vstack([col5, prev5])

  # ... and so on, until we have index [23] and [22] and x24

  res = numpy.hstack([x1, x2, x3, x4, x5])
  return res 

def shift_two(arr):
    arrT = arr.transpose()
    arrT_shape = arrT.shape[0]
    new_size = 2 * arrT_shape

    col1 = arrT[:, [0]]
    prev1 = numpy.zeros([new_size, 1])
    x1 = numpy.vstack([col1, prev1])

    col22 = arrT[:, [1]]
    col21 = arrT[:, [0]]
    prev2 = numpy.zeros([arrT_shape, 1])
    x2 = numpy.vstack([col22, col21, prev2])

    col32 = arrT[:, [2]]
    col31 = arrT[:, [1]]
    col30 = arrT[:, [0]]
    x3 = numpy.vstack([col32, col31, col30])

    col42 = arrT[:, [3]]
    col41 = arrT[:, [2]]
    col40 = arrT[:, [1]]
    x4 = numpy.vstack([col42, col41, col40])

    col52 = arrT[:, [4]]
    col51 = arrT[:, [3]]
    col50 = arrT[:, [2]]
    x5 = numpy.vstack([col52, col51, col50])

    # ... and so on, until we have index [23], [22], [21] and x24

    res = numpy.hstack([x1, x2, x3, x4, x5])
    return res

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

print(arr1)

print('\n\n')
one = shift_one(arr1)
print(one)

print('\n\n')
two = shift_two(arr1)
print(two)

基本上,我有一個問題如何編寫 function,它將用給定的 N 移動它......我知道如何一步一步地編寫它,但是我在將它轉換成更有用的東西時遇到了問題。 謝謝你。

再次,以 5 列數組為例(原始數組有 24 列):

在此處輸入圖像描述

循環的

如果您想針對一般情況執行此操作,您可以從一個簡單的循環開始。 如果輸入數組的形狀為(M, N) ,則 output 將為(M * (delay + 1), N)

堆疊是組合 arrays 的一種方式。 您可以通過始終將結果加倍來最小化所需的堆棧數:

def stagger(a, delay):
    m = a.shape[0]
    z = 1
    d = delay + 1
    while z < d:
        k = min(d - z, z)    # This will only kick in for the last iteration
        new = np.concatenate([np.zeros((m * k, z)), a[:m * k, :-z]], axis=1)
        a = np.concatenate([a, new], axis=0)
        z *= 2
    return a

矢量化

話雖這么說,有一種完全矢量化的方法可以使用np.lib.stride_tricks.asstrided的怪物來做到這一點。 想象一個數組,它是原始數據的第一行,在左側填充了delay + 1零:

>>> d = delay + 1    # delay = 7
>>> row = np.concatenate([np.zeros(d), a[0]])
>>> row
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7., 
        8.,  9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23.])

您可以通過添加一個假的第二維來查看這個數組(不復制數據)作為一個交錯的 2D 緩沖區,該第二維的步幅比它應該的短一個元素:

>>> m, n = a.shape
>>> staggered_row = np.lib.stride_tricks.as_strided(row[d:], shape=(d, n), strides=(-row.strides[0], row.strides[0]))
>>> staggered_row
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.],
       [ 0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.,
        11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.],
       [ 0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.,
        10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21.],
       [ 0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,
         9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20.],
       [ 0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,
         8.,  9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,
         7.,  8.,  9., 10., 11., 12., 13., 14., 15., 16., 17., 18.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,
         6.,  7.,  8.,  9., 10., 11., 12., 13., 14., 15., 16., 17.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,
         5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14., 15., 16.]])

在這里,負步幅將零填充的元素添加到數組中。 請記住,這通常是不安全的,應格外小心。 默認情況下,output 不可寫,因為所有行都指向大致相同的 memory 位置。

現在想象對你的整個數組做同樣的事情:填充並添加一個新的維度,讓你回到填充。 如果您仔細訂購尺寸,視圖的重塑將創建一個新副本,該副本看起來完全符合您的要求。 具體來說,從形狀(M, N)開始,我們填充到(D + M, N) ,創建一個為(D, M, N)的視圖,然后重新整形為(D * M, N)

def staggerx(a, delay):
    d = delay + 1
    m, n = a.shape
    padded = np.concatenate([np.zeros((m, d)), a], axis=1)
    view = np.lib.stride_tricks.as_strided(padded[:, d:], shape=(d, m, n), strides=(-padded.strides[1], padded.strides[0], padded.strides[1]))
    result = view.reshape(-1, n)
    return result

一個瘋狂的跨步數組的重塑總是會產生一個副本,因為順便說一下數據是不連續的。

如果數據不是太龐大,連接幾次就可以了:

>>> x
array([[  0,   1,   2,   3,   4],
       [  2,   2,   2,   2,   2],
       [  0,   0,   0,   0,   0],
       [324, 324, 324, 324, 324]])
>>> np.concatenate([x] + [np.concatenate([np.zeros(x.shape[0]*i).reshape(-1, i), x[: , i:]] ,axis=1) for i in range(1,x.shape[1])], axis=0)
array([[  0.,   1.,   2.,   3.,   4.],
       [  2.,   2.,   2.,   2.,   2.],
       [  0.,   0.,   0.,   0.,   0.],
       [324., 324., 324., 324., 324.],
       [  0.,   1.,   2.,   3.,   4.],
       [  0.,   2.,   2.,   2.,   2.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0., 324., 324., 324., 324.],
       [  0.,   0.,   2.,   3.,   4.],
       [  0.,   0.,   2.,   2.,   2.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0.,   0., 324., 324., 324.],
       [  0.,   0.,   0.,   3.,   4.],
       [  0.,   0.,   0.,   2.,   2.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0.,   0.,   0., 324., 324.],
       [  0.,   0.,   0.,   0.,   4.],
       [  0.,   0.,   0.,   0.,   2.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0.,   0.,   0.,   0., 324.]])

每次我生成一個4xi零矩陣,並從原始矩陣中取出i+1:列來生成下一部分。 最后,我將所有這些 arrays 連接起來。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM