3

I have problem during low-pass interpolation, I have to fill 1D array with zeros before processing it.

I have something like this: [1 2 3 4 5 6]

I want to have array like this [1 0 2 0 3 0 4 0 5 0 6] so it is L-1 zeros in array where L is the number of all values inside array before zero stuffing.

How to do it in Python?

6 Answers 6

14

You can assign an unpadded list of values into a slice of another list of zeros:

original_list = range(1,7)                 # [1,2,3,4,5,6]
padded_list = [0]*(2*len(original_list)-1) # [0,0,0,0,0,0,0,0,0,0,0]
padded_list[::2] = original_list           # [1,0,2,0,3,0,4,0,5,0,6]

This can translate to numpy too, though as Jaime pointed out in a comment, it's even easier to use numpy.insert:

import numpy as np

arr = np.arange(1, 7)              # array([1, 2, 3, 4, 5, 6])
np.insert(arr, slice(1, None), 0)  # array([1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6])
Sign up to request clarification or add additional context in comments.

1 Comment

Is slice(1,None,2) right? For me (1,None,1) was resulting in the expected output.
3

I had to apply that for bigger amount of data real time, so I checked the performance and np.insert seems to be the slowest one on Python 2.7:

np.insert:                     1.393 ms
list:                          0.406 ms
np.repeat then zero out:       0.409 ms
np.zeros then assign value:    0.073 ms

Here's the test code:

import time
import numpy as np

start = 0
limit = 30000000

def tic():
    global start
    start = time.clock()

def toc(text):
    print("%-30s %.3f ms" % (text, time.clock()-start))

original_list = range(1,limit)
original_array = np.arange(1, limit)

tic()
insert_array = np.insert(original_array, slice(1, None), 0)
toc("np.insert:")

tic()
padded_list = [0]*(2*len(original_list)-1)
padded_list[::2] = original_list
toc("list:")

tic()
repeat_array = np.repeat(original_array, 2)
repeat_array[1::2] = 0
toc("np.repeat then zero out:")

tic()
padded_array = np.zeros(2*len(original_list)-1, dtype=original_array.dtype)
padded_array[::2] = original_array
toc("np.zeros then assign value:")

Comments

0
l = [1, 2, 3, 4, 5, 6]

def zero_pad(l):
    r = []
    for x in l:
        r.append(x)
        r.append(0)
    return r[:-1]

print zero_pad(l)

Will print:

[1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6]

Comments

0

One simplistic approach:

>>> i = [1,2,3,4,5,6]
>>> [i.insert(i.index(x)+1,0) for x in i[:-1]]
[None, None, None, None, None]
>>> i
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6]

The same as above, expanded:

>>> for x in i[:-1]:
...     i.insert(i.index(x)+1,0)
...
>>> i
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6]

2 Comments

There's no good reason to use the list comprehension version. The explicit loop is much easier to understand, and doesn't build a useless list of Nones.
Actually, as I read this again, there's a bit more wrong. Using i.index is not necessary, and it will give the wrong results if there are duplicate values in the list. Since you know that you want to insert a zero at every position in reverse order you should just use for x in range(len(i)-1,0,-1): i.insert(x, 0)
0
def zero(array):
    for i in range(1, len(array)):
        array.insert(i+i-1,0)
    return array

array = [1, 2, 3, 4, 5, 6]
newArray = zero(array)

Comments

0

Mandatory itertools approach:

>>> from itertools import izip, repeat, chain
>>> list(chain.from_iterable(izip(el, repeat(0))))[:-1]
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6]

Much better itertools approach...

from itertools import islice, izip, repeat, chain
blah = list (islice (chain.from_iterable (izip(repeat (0), your_seq)), 1, None))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.