0

Is there a built-in Numpy function to shift (roll + pad) an 1D array?

Something like this:

import numpy as np


def roll_pad(a, t):
    b = np.roll(a, t)
    if t >= 0:
        b[:t] = 0
    else:
        b[t:] = 0
    return b

z = np.array([1, 2, 3, 4, 5, 6])
print(z)
print(roll_pad(z, 2))  # [0 0 1 2 3 4]
print(roll_pad(z, -2))  # [3 4 5 6 0 0]
Basj
  • 41,386
  • 99
  • 383
  • 673
  • `np.roll` may be overkill for this, since it can handle multidimensions. At its core it just makes a `np.empty_list` array, and copies slices from the source to this array. So you could make a `np.zeros_like(a)` and copy a slice of `a` to it. – hpaulj Mar 20 '23 at 17:08
  • read the `pad` code – hpaulj Mar 20 '23 at 17:10
  • @hpaulj Is there a ready-to-use built-in function that does `roll_pad` directly? – Basj Mar 20 '23 at 19:36
  • Can't you take a hint from my comment? NO! – hpaulj Mar 20 '23 at 20:30
  • @hpaulj It depends what you mean ;) Of course I know https://numpy.org/doc/stable/reference/generated/numpy.pad.html but I don't think it can do my `roll_pad` in one line without defining my own utility function... – Basj Mar 20 '23 at 20:38
  • Is there some special virtue in writing a one-liner? This isn't Perl! `np.roll' is 25 lines of code, plus documentation. You aren't trying to do something common place, so don't expect a special `numpy` building block just for you. – hpaulj Mar 20 '23 at 20:56
  • I was thinking of something like `k=3; res=np.zeros_like(x); res[-k:] = x[:k];res`. But there are 4 combinations of front/end slicing. If you take time to look at any `numpy` function like `pad` or `roll`, you'll see lots of code that interprets in arguments, and sets up the task. The 'work' is often done by just a few lines at the end. Read some `numpy` code; you might learn something. – hpaulj Mar 20 '23 at 21:16
  • `np.pad(x[3:6],(3,5))` is another example of slicing some part of an array, and padding it with zeros. The slice doesn't have to be at the start or end, and the final length can change. That's "one line", but `np.pad` is even more complicated than `np.roll`, since it can pad many different ways. – hpaulj Mar 20 '23 at 23:04
  • Yes @hpaulj, I'm happy with the (working) lines of code I currently have (in my question), but it was just out of curiosity: sometimes you realize that a function already exists, built-in. That was the goal of this question :) – Basj Mar 20 '23 at 23:29

1 Answers1

-1

Yes, there is a built-in numpy function to roll and pad a 1D array, it is called numpy.roll combined with numpy.pad.

Here is an example implementation of your function roll_pad using these two numpy functions:

import numpy as np

def roll_pad(a, t):
    if t >= 0:
        b = np.pad(a[:-t], (t, 0), mode='constant')
    else:
        b = np.pad(a[-t:], (0, -t), mode='constant')
    return b

z = np.array([1, 2, 3, 4, 5, 6])
print(z)
print(roll_pad(z, 2))  # [0 0 1 2 3 4]
print(roll_pad(z, -2))  # [3 4 5 6 0 0]

This implementation uses numpy.pad to pad the array with zeros before or after the rolled array, depending on the sign of the shift value t. Note that mode='constant' is used to pad with zeros. The slicing is also changed to exclude the last t elements when t is positive, or the first t elements when t is negative, to ensure that the original array is not repeated after padding.

  • Thanks but this is not a built-in function, this is a custom function similar to the one in my question. – Basj Mar 21 '23 at 10:30