Etienne Prothon
Etienne Prothon

Reputation: 1082

Numpy resize and fill with specific value

How can i resize a numpy array and fill it with a specific value (if some dimension is extended) ?

I find a way to extend my array with np.pad but I can't shorten it:

>>> import numpy as np
>>> a = np.ndarray((5, 5), dtype=np.uint16)
>>> a
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]], dtype=uint16)
>>> np.pad(a, ((0, 1), (0,3)), mode='constant', constant_values=9)
array([[0, 0, 0, 0, 0, 9, 9, 9],
       [0, 0, 0, 0, 0, 9, 9, 9],
       [0, 0, 0, 0, 0, 9, 9, 9],
       [0, 0, 0, 0, 0, 9, 9, 9],
       [0, 0, 0, 0, 0, 9, 9, 9],
       [9, 9, 9, 9, 9, 9, 9, 9]], dtype=uint16)

And if i use resize i can't specify the value that I want to use.

>>> a.fill(5)
>>> a.resize((2, 7))
>>> a
array([[5, 5, 5, 5, 5, 5, 5],
       [5, 5, 5, 5, 5, 5, 5]], dtype=uint16)

But i would like

>>> a
array([[5, 5, 5, 5, 5, 9, 9],
       [5, 5, 5, 5, 5, 9, 9]], dtype=uint16)

After some test I create this function but it's only work when you change x_value or with a lower y_value, if you need to increase y dimension it doesn't work, why ?

VALUE_TO_FILL = 9
def resize(self, x_value, y_value):
    x_diff = self.np_array.shape[0] - x_value
    y_diff = self.np_array.shape[1] - y_value
    self.np_array.resize((x_value, y_value), refcheck=False)
    if x_diff < 0:
        self.np_array[x_diff:, :] = VALUE_TO_FILL
    if y_diff < 0:
        self.np_array[:, y_diff:] = VALUE_TO_FILL

Upvotes: 2

Views: 3732

Answers (2)

hpaulj
hpaulj

Reputation: 231615

Your array has a fixed size data buffer. You can reshape the array without changing that buffer. You can take a slice (view) without changing the buffer. But you can't add values to the array without changing the buffer.

In general resize returns an new array with a new data buffer.

pad is a complex function to handle general cases. But the simplest approach is to create the empty target array, fill it, and then copy the input into the right place.

Alternatively pad could create the fill arrays and concatenate them with the original. But concatenate also makes the empty return and copies.

A do it yourself pad with clipping could be structured as:

n,m = X.shape
R = np.empty((k,l))
R.fill(value)
<calc slices from n,m,k,l>
R[slice1] = X[slice2]

Calculating the slices may require if-else tests or equivalent min/max. You can probably work out those details.


This may be all that is needed

R[:X.shape[0],:X.shape[1]]=X[:R.shape[0],:R.shape[1]]

That's because there's no problem if a slice is larger than the dimension.

In [37]: np.arange(5)[:10]
Out[37]: array([0, 1, 2, 3, 4])

Thus, for example:

In [38]: X=np.ones((3,4),int)    
In [39]: R=np.empty((2,5),int)
In [40]: R.fill(9)

In [41]: R[:X.shape[0],:X.shape[1]]=X[:R.shape[0],:R.shape[1]]

In [42]: R
Out[42]: 
array([[1, 1, 1, 1, 9],
       [1, 1, 1, 1, 9]])

Upvotes: 5

3kt
3kt

Reputation: 2553

To shorten it, you can use negative values in slice :

>>> import numpy as np
>>> a = np.ndarray((5, 5), dtype=np.uint16)
>>> a
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]], dtype=uint16)
>>> b = a[0:-1,0:-3]
>>> b
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0]], dtype=uint16)

Upvotes: 0

Related Questions