Saya ingin tahu bagaimana saya dapat mengisi array numpy 2D dengan nol menggunakan python 2.6.6 dengan numpy versi 1.5.0. Maaf! Tetapi ini adalah batasan saya. Oleh karena itu saya tidak dapat menggunakan np.pad
. Misalnya, saya ingin mengisi a
angka nol sehingga bentuknya cocok b
. Alasan mengapa saya ingin melakukan ini adalah agar saya dapat melakukan:
b-a
seperti yang
>>> 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]])
Satu-satunya cara yang dapat saya pikirkan untuk melakukan ini adalah menambahkan, namun ini tampaknya sangat jelek. apakah ada solusi yang lebih bersih yang mungkin digunakan b.shape
?
Edit, Terima kasih atas jawaban MSeiferts. Saya harus membersihkannya sedikit, dan inilah yang saya dapatkan:
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
padded = np.zeros(b.shape)
padded[tuple(slice(0,n) for n in a.shape)] = a
NumPy 1.7.0 (saat
numpy.pad
ditambahkan) sudah cukup tua sekarang (dirilis pada 2013) jadi meskipun pertanyaan menanyakan cara tanpa menggunakan fungsi itu, saya pikir akan berguna untuk mengetahui bagaimana itu bisa dicapai dengan menggunakannumpy.pad
.Sebenarnya cukup sederhana:
>>> 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.]])
Dalam hal ini yang saya gunakan
0
adalah nilai default untukmode='constant'
. Tapi itu juga bisa ditentukan dengan meneruskannya secara eksplisit:>>> 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.]])
Untuk berjaga-jaga jika argumen kedua (
[(0, 1), (0, 1)]
) tampak membingungkan: Setiap item daftar (dalam hal ini tupel) sesuai dengan dimensi dan item di dalamnya mewakili padding sebelum (elemen pertama) dan sesudah (elemen kedua). Begitu:Dalam hal ini padding untuk sumbu pertama dan kedua adalah identik, jadi seseorang juga bisa melewatkan 2-tuple:
>>> 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.]])
Jika padding sebelum dan sesudah identik, seseorang bahkan dapat menghilangkan tuple (tidak berlaku dalam kasus ini):
>>> 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.]])
Atau jika padding sebelum dan sesudah identik tetapi berbeda untuk sumbu, Anda juga dapat menghilangkan argumen kedua di tupel dalam:
>>> 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.]])
Namun saya cenderung lebih suka untuk selalu menggunakan yang eksplisit, karena mudah untuk membuat kesalahan (ketika harapan NumPys berbeda dari niat Anda):
>>> 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.]])
Di sini NumPy berpikir Anda ingin mengisi semua sumbu dengan 1 elemen sebelum dan 2 elemen setelah setiap sumbu! Bahkan jika Anda menginginkannya untuk diisi dengan 1 elemen dalam sumbu 1 dan 2 elemen untuk sumbu 2.
Saya menggunakan daftar tupel untuk padding, perhatikan bahwa ini hanya "konvensi saya", Anda juga dapat menggunakan daftar daftar atau tupel tupel, atau bahkan tupel array. NumPy hanya memeriksa panjang argumen (atau jika tidak memiliki panjang) dan panjang setiap item (atau jika memiliki panjang)!
sumber
mode='constant'
adalah default yang masuk akal, jadi padding dengan nol dapat dicapai tanpa perlu kata kunci opsional apa pun, yang mengarah ke kode yang sedikit lebih mudah dibaca.Saya mengerti bahwa masalah utama Anda adalah Anda perlu menghitung
d=b-a
tetapi array Anda memiliki ukuran yang berbeda. Tidak perlu bantalan perantarac
Anda dapat menyelesaikan ini tanpa padding:
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
Keluaran:
[[ 2. 2. 2. 2. 2. 3.] [ 2. 2. 2. 2. 2. 3.] [ 2. 2. 2. 2. 2. 3.] [ 3. 3. 3. 3. 3. 3.]]
sumber
Jika Anda perlu menambahkan pagar 1 ke array:
>>> 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]])
sumber
Saya tahu saya agak terlambat untuk ini, tetapi jika Anda ingin melakukan padding relatif (alias padding tepi), inilah cara Anda dapat menerapkannya. Perhatikan bahwa contoh pertama dari tugas menghasilkan bantalan-nol, sehingga Anda dapat menggunakan ini untuk bantalan-nol dan bantalan relatif (ini adalah tempat Anda menyalin nilai tepi dari larik asli ke dalam larik yang diisi).
def replicate_padding(arr): """Perform replicate padding on a numpy array.""" new_pad_shape = tuple(np.array(arr.shape) + 2) # 2 indicates the width + height to change, a (512, 512) image --> (514, 514) padded image. padded_array = np.zeros(new_pad_shape) #create an array of zeros with new dimensions # perform replication padded_array[1:-1,1:-1] = arr # result will be zero-pad padded_array[0,1:-1] = arr[0] # perform edge pad for top row padded_array[-1, 1:-1] = arr[-1] # edge pad for bottom row padded_array.T[0, 1:-1] = arr.T[0] # edge pad for first column padded_array.T[-1, 1:-1] = arr.T[-1] # edge pad for last column #at this point, all values except for the 4 corners should have been replicated padded_array[0][0] = arr[0][0] # top left corner padded_array[-1][0] = arr[-1][0] # bottom left corner padded_array[0][-1] = arr[0][-1] # top right corner padded_array[-1][-1] = arr[-1][-1] # bottom right corner return padded_array
Analisis Kompleksitas:
Solusi optimal untuk ini adalah metode bantalan numpy. Setelah rata-rata untuk 5 kali berjalan, np.pad dengan bantalan relatif hanya
8%
lebih baik daripada fungsi yang ditentukan di atas. Ini menunjukkan bahwa ini adalah metode yang cukup optimal untuk bantalan relatif dan bantalan nol.#My method, replicate_padding start = time.time() padded = replicate_padding(input_image) end = time.time() delta0 = end - start #np.pad with edge padding start = time.time() padded = np.pad(input_image, 1, mode='edge') end = time.time() delta = end - start print(delta0) # np Output: 0.0008790493011474609 print(delta) # My Output: 0.0008130073547363281 print(100*((delta0-delta)/delta)) # Percent difference: 8.12316715542522%
sumber