0

Say I have a numpy array

import numpy as np

arr = np.zeros(20)

arr[::4] = func = np.arange(5) # Excuse the setup hack

print(arr)

i.e.

[0. 0. 0. 0. 1. 0. 0. 0. 2. 0. 0. 0. 3. 0. 0. 0. 4. 0. 0. 0.] ,

How can I right-pad the zeroes in the array without a for-loop to give the following?

arr_expected = np.array([0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4])

I should add that the stride length is irregular/arbitrary - NOT every 4 as in the example.

Here is a second example:

import numpy as np
arr = np.zeros(20)
arr[2]=4
arr[9]=3
arr[18]=101
print(arr)

gives:

[ 0. 0. 4. 0. 0. 0. 0. 0. 0. 3. 0. 0. 0. 0. 0. 0. 0. 0. 101. 0.] ,

with the expected output being

arr_expected = np.array([0,0,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,101,101])

Note that this is not a cumulative sum (although, in this case, func is a cumulative sum but only at certain indices in an original array). I have thought about impulses and transfer functions, uneven square waves, interpolation, sliding masks.....

PS The zeros could be any other pad value - np.nan etc. or even an arbitrary array. The point is to fill in the gaps with the values at predefined indices.

Huge thanks as ever

jtlz2
  • 7,700
  • 9
  • 64
  • 114
  • Why the downvote? Also a comment - which came across as rude - asking for a second example, which I then added, but which ordered me "not to explain"... There was I thinking the question box was a free-form one..... – jtlz2 Apr 07 '22 at 15:07
  • @QuangHoang This is a duplicate but for the fact that my case is 1D not 2D (which I think is a sufficiently-simpler case that might warrant a hopefully-simpler solution)! If others vote to close this one I will do the same. Thanks for the spot, much appreciated! – jtlz2 Apr 07 '22 at 15:22

1 Answers1

1

At first, we append a value bigger than the maximum of values in the array to get number of repeatation correctly. Furthermore, for doing so, we need to preserve the order of magnitudes in the array, which can be achieved by argsort:

arr = np.append(arr, max(arr) + 1)
unique, inds = np.unique(arr, return_index=True)
sort_ = inds[:-1].argsort()
inds = np.sort(inds)
diff = np.diff(inds)
result = np.repeat(unique[:-1][sort_], diff)

This code get the true result:

[  0   0   4   4   4   4   4   4   4   3   3   3   3   3   3   3   3   3 101 101]
Ali_Sh
  • 2,667
  • 3
  • 43
  • 66
  • 2
    anything related to `np.unique` is probably not correct, e.g. `arr = [0,2,0,1,0,2,0,0]`. – Quang Hoang Apr 07 '22 at 16:58
  • @QuangHoang, I agree. This answer is based on the example that the OP provided in which the nonzero values in the array are unique (not repeated). If values could be repeated, there are useful answers in [the provided link](https://stackoverflow.com/questions/30488961/fill-zero-values-of-1d-numpy-array-with-last-non-zero-values) in this regard. – Ali_Sh Apr 07 '22 at 20:27