2016-03-02 128 views
16

我想知道如何用numpy 1.5.0版使用python 2.6.6填充二維numpy數組。抱歉!但這些是我的限制。所以我不能使用np.pad。例如,我想用零填充a,使其形狀匹配b。爲什麼我想這樣做的原因是,所以我可以做的:python如何用零填充numpy數組

b-a 

這樣

>>> a 
array([[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.]]) 
>>> b 
array([[ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.]]) 
>>> c 
array([[1, 1, 1, 1, 1, 0], 
     [1, 1, 1, 1, 1, 0], 
     [1, 1, 1, 1, 1, 0], 
     [0, 0, 0, 0, 0, 0]]) 

我認爲這樣做是追加的唯一途徑,然而,這似乎是相當難看。有沒有更清潔的解決方案可能使用b.shape

編輯, 謝謝MSeiferts的回答。我不得不把它清理乾淨了一下,這是我得到了什麼:

def pad(array, reference_shape, offsets): 
    """ 
    array: Array to be padded 
    reference_shape: tuple of size of ndarray to create 
    offsets: list of offsets (number of elements must be equal to the dimension of the array) 
    will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets 
    """ 

    # Create an array of zeros with the reference shape 
    result = np.zeros(reference_shape) 
    # Create a list of slices from offset to offset + shape in each dimension 
    insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)] 
    # Insert the array in the result at the specified offsets 
    result[insertHere] = array 
    return result 
+0

我可以建議你一個辦法做到這一點沒有填充? – purpletentacle

回答

44

很簡單,你創建一個使用參照形狀包含零的數組:

result = np.zeros(b.shape) 
# actually you can also use result = np.zeros_like(b) 
# but that also copies the dtype not only the shape 

,然後將數組,其中你需要它:

result[:a.shape[0],:a.shape[1]] = a 

,瞧你軟墊它:

print(result) 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

您也可以使它有點如果你定義了更一般的在您的左上元素應該被插入

result = np.zeros_like(b) 
x_offset = 1 # 0 would be what you wanted 
y_offset = 1 # 0 in your case 
result[x_offset:a.shape[0]+x_offset,y_offset:a.shape[1]+y_offset] = a 
result 

array([[ 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1.], 
     [ 0., 1., 1., 1., 1., 1.], 
     [ 0., 1., 1., 1., 1., 1.]]) 

但隨後要小心,你沒有偏移大於允許的。例如,對於x_offset = 2,這將失敗。


如果您有任意數量的維度,您可以定義切片的列表以插入原始數組。我發現玩這個遊戲很有趣,並且創建了一個填充函數,只要數組和參考的維數相同並且偏移量不是很大,就可以填充(使用偏移量)任意形狀的數組。

def pad(array, reference, offsets): 
    """ 
    array: Array to be padded 
    reference: Reference array with the desired shape 
    offsets: list of offsets (number of elements must be equal to the dimension of the array) 
    """ 
    # Create an array of zeros with the reference shape 
    result = np.zeros(reference.shape) 
    # Create a list of slices from offset to offset + shape in each dimension 
    insertHere = [slice(offset[dim], offset[dim] + array.shape[dim]) for dim in range(a.ndim)] 
    # Insert the array in the result at the specified offsets 
    result[insertHere] = a 
    return result 

及一些測試情況:

import numpy as np 

# 1 Dimension 
a = np.ones(2) 
b = np.ones(5) 
offset = [3] 
pad(a, b, offset) 

# 3 Dimensions 

a = np.ones((3,3,3)) 
b = np.ones((5,4,3)) 
offset = [1,0,0] 
pad(a, b, offset) 
+0

啊很好看。這可以推廣到1D數組或任何數組? – user2015487

+0

@ user2015487 - 您的意思是接受任意維度的函數,還是隻針對另一維度的函數? – MSeifert

4

我明白你的主要問題是,你需要計算d=b-a但你的陣列有不同的尺寸。有沒有需要中間填充c

就可以解決這個不填充:

import numpy as np 

a = np.array([[ 1., 1., 1., 1., 1.], 
       [ 1., 1., 1., 1., 1.], 
       [ 1., 1., 1., 1., 1.]]) 

b = np.array([[ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.]]) 

d = b.copy() 
d[:a.shape[0],:a.shape[1]] -= a 

print d 

輸出:現在

[[ 2. 2. 2. 2. 2. 3.] 
[ 2. 2. 2. 2. 2. 3.] 
[ 2. 2. 2. 2. 2. 3.] 
[ 3. 3. 3. 3. 3. 3.]] 
+0

的確,對於他的具體情況,他不一定需要填充,但這是填充和您的方法等效的極少數算術運算之一。不過不錯的答案! – MSeifert

20

NumPy的1.7(當加入np.pad)是很老的(它於2013年發佈),所以即使這個問題需要一種沒有這種功能的方式,我認爲了解如何使用np.pad可以實現這一點可能是有用的。

這其實很簡單:在這種情況下,我使用了0mode='constant'默認值

>>> import numpy as np 
>>> a = np.array([[ 1., 1., 1., 1., 1.], 
...    [ 1., 1., 1., 1., 1.], 
...    [ 1., 1., 1., 1., 1.]]) 
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant') 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

>>> np.pad(a, [(0, 1), (0, 1)], mode='constant', constant_values=0) 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

萬一第二個參數([(0, 1), (0, 1)])顯得撲朔迷離:但它也可以通過在傳遞明確指定每個列表項(在這種情況下,元組)對應於一維和項目其中代表填充之前(第一元件)和(第二元件)。所以:

[(0, 1), (0, 1)] 
     ^^^^^^------ padding for second dimension 
^^^^^^-------------- padding for first dimension 

    ^------------------ no padding at the beginning of the first axis 
    ^--------------- pad with one "value" at the end of the first axis. 

在這種情況下,用於第一和第二軸的填補是相同的,所以一個還可以只通過在2元組:

>>> np.pad(a, (0, 1), mode='constant') 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

在殼體之前的填充和後同樣一個甚至可以忽略元組(不適用在這種情況下,雖然):

>>> np.pad(a, 1, mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.]]) 

或者,如果之前和之後的填充是相同的,但不同的軸,你也可以忽略第二個參數在內部的元組:

>>> np.pad(a, [(1,), (2,)], mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) 

不過,我更願意總是使用明確的一個,因爲它只是容易犯錯誤時(NumPys期望從你的意圖有所不同):

>>> np.pad(a, [1, 2], mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0.]]) 

這裏NumPy認爲你想用1個元素填充所有的軸,每個軸之後填充2個元素!即使你打算在1軸上添加1個元素,在2軸上添加2個元素。

我使用了用於填充的元組列表,注意這只是「我的約定」,您也可以使用列表列表或者元組的元組,或者甚至是數組的元組。 NumPy只是檢查參數的長度(或者它沒有長度)和每個項目的長度(或者它是否有長度)!

0

如果您需要1秒的圍欄添加到一個數組:

mat = np.zeros((4,4), np.int32) mat array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) mat[0,:] = mat[:,0] = mat[:,-1] = mat[-1,:] = 1 mat array([[1, 1, 1, 1], [1, 0, 0, 1], [1, 0, 0, 1], [1, 1, 1, 1]])

謝謝。