[英]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.