Thomas
Thomas

Reputation: 545

Zero padding multiple values in Python

In another SO, this is a solution for adding a single zero between values in a numpy.array:

import numpy as np

arr = np.arange(1, 7)                 # array([1, 2, 3, 4, 5, 6])
np.insert(arr, slice(1, None, 2), 0)  # array([1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6])

How would I add more zeros between each value in original array? For example, 5 zeros:

np.array([1, 0, 0, 0, 0, 0,
          2, 0, 0, 0, 0, 0,
          3, 0, 0, 0, 0, 0,
          4, 0, 0, 0, 0, 0,
          5, 0, 0, 0, 0, 0, 6])

Upvotes: 3

Views: 2710

Answers (3)

Thijs van Dien
Thijs van Dien

Reputation: 6626

If it doesn't need to be pure NumPy, you could do something like this:

import numpy

def pad(it, zero_count):
    it = iter(it)
    yield next(it)
    while True:
        element = next(it)
        for n in xrange(zero_count):
            yield 0
        yield element

arr = numpy.fromiter(pad(xrange(1, 7), 5), int, -1)

or if you want to optimize allocation a bit:

values = xrange(1, 7)
zero_count = 5
total_length = len(values) + max(0, len(values)-1) * zero_count
arr = numpy.fromiter(pad(values, zero_count), int, total_length)

Upvotes: 0

shx2
shx2

Reputation: 64368

You can create a 2dim array, and flatten it:

import numpy as np
a = np.arange(1,7)
num_zeros = 5
z = np.zeros((a.size, num_zeros))

np.append(a[:,np.newaxis], z, axis=1)
array([[ 1.,  0.,  0.,  0.,  0.,  0.],
       [ 2.,  0.,  0.,  0.,  0.,  0.],
       [ 3.,  0.,  0.,  0.,  0.,  0.],
       [ 4.,  0.,  0.,  0.,  0.,  0.],
       [ 5.,  0.,  0.,  0.,  0.,  0.],
       [ 6.,  0.,  0.,  0.,  0.,  0.]])

np.append(a[:,np.newaxis], z, axis=1).flatten()
array([ 1.,  0.,  0.,  0.,  0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  3.,
        0.,  0.,  0.,  0.,  0.,  4.,  0.,  0.,  0.,  0.,  0.,  5.,  0.,
        0.,  0.,  0.,  0.,  6.,  0.,  0.,  0.,  0.,  0.])

np.append(a[:,np.newaxis], z, axis=1).flatten()[:-num_zeros]
array([ 1.,  0.,  0.,  0.,  0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  3.,
        0.,  0.,  0.,  0.,  0.,  4.,  0.,  0.,  0.,  0.,  0.,  5.,  0.,
        0.,  0.,  0.,  0.,  6.])

Upvotes: 3

Warren Weckesser
Warren Weckesser

Reputation: 114946

Here's one way, using insert:

In [31]: arr
Out[31]: array([1, 2, 3, 4, 5, 6])

In [32]: nz = 5

In [33]: pos = np.repeat(range(1,len(arr)), nz)

In [34]: pos
Out[34]: 
array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
   5, 5])

In [35]: np.insert(arr, pos, 0)
Out[35]: 
array([1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
       0, 5, 0, 0, 0, 0, 0, 6])

Here's another way. This method requires no temporary arrays, so it should be much more efficient. The padded array b is preallocated using np.zeros, and then the values from arr are copied into b with a sliced assignment:

In [45]: b = np.zeros(1 + (nz+1)*(arr.size-1), dtype=arr.dtype)

In [46]: b.size
Out[46]: 31

In [47]: b[::nz+1] = arr

In [48]: b
Out[48]: 
array([1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
       0, 5, 0, 0, 0, 0, 0, 6])

Upvotes: 2

Related Questions