0

I wish to create a variable array of numbers in numpy while skipping a chunk of numbers. For instance, If I have the variables:

m = 5

k = 3

num = 50

I want to create a linearly spaced numpy array starting at num and ending at num - k, skip k numbers and continue the array generation. Then repeat this process m times. For example, the above would yield:

np.array([50, 49, 48, 47, 44, 43, 42, 41, 38, 37, 36, 35, 32, 31, 30, 29, 26, 25, 24, 23])

How can I accomplish this via Numpy?

6
  • I'm not sure what you mean. Perhaps some code that does what you want with normal Python lists could help illustrate this? Commented Mar 24, 2021 at 22:13
  • I've clarified the question above Commented Mar 24, 2021 at 22:22
  • @J_code After 29 it should be 26,25,24,23 Commented Mar 24, 2021 at 22:33
  • @CutePanda fixed Commented Mar 24, 2021 at 22:46
  • The step sizes seems to be fixed to one, is that correct? Commented Mar 24, 2021 at 22:59

4 Answers 4

4

You can try:

import numpy as np

m = 5
k = 3
num = 50
np.hstack([np.arange(num - 2*i*k, num - (2*i+1)*k - 1, -1) for i in range(m)])

It gives:

array([50, 49, 48, 47, 44, 43, 42, 41, 38, 37, 36, 35, 32, 31, 30, 29, 26,
       25, 24, 23])

Edit:

@JanChristophTerasa posted an answer (now deleted) that avoided Python loops by masking some elements of an array obtained using np.arange(). Here is a solution inspired by that idea. It works much faster than the above one:

import numpy as np

m = 5
k = 3
num = 50
x = np.arange(num, num - 2*k*m , -1).reshape(-1, 2*k)
x[:, :k+1].ravel()
Sign up to request clarification or add additional context in comments.

4 Comments

I didn't get my solution to work in the end.
@JanChristophTerasa I was going to suggest how to fix it, but it was gone by then. It was a nice idea, worth being posted.
I just posted another solution using masks which actually works. It's quite a bit slower than your optimized solution, though, well done!
Great effort. Your edit inspired by @JanChristopTerasa's solution is very elegant and clear
1

We can use a mask and np.tile:

def mask_and_tile(m=5, k=3, num=50):
    a = np.arange(num, num - 2 * m * k, -1) # create numbers
    mask = np.ones(k * 2, dtype=bool) # create mask
    mask[k+1:] = False # set appropriate elements to False
    mask = np.tile(mask, m) # repeat mask m times
    result = a[mask] # mask our numbers
    return result

Or we can use a mask and just toggle the appropriate element:

def mask(m=5, k=3, num=50):
    a = np.arange(num, num - 2 * m * k, -1) # create numbers
    mask = np.ones_like(a, dtype=bool).reshape(-1, k)
    mask[1::2] = False
    mask[1::2, 0] = True
    result = a[mask.flatten()]
    return result

Comments

0

This will work fine:

import numpy as np
m = 5
k = 3
num = 50
h=0
x = np.array([])
for i in range(m):
    x = np.append(x, range(num-h,num-h-k-1,-1))
    h+=2*k
print(x)

Output

[50. 49. 48. 47. 44. 43. 42. 41. 38. 37. 36. 35. 32. 31. 30. 29. 26. 25.
 24. 23.]

2 Comments

List append is better than np.append
@hpaulj I know right, and deque() is even more better than list for append, pop operation, but he mentioned in question that he want to accomplish it via NumPy, that's why this approach.
0

One way of doing this is making a 2D grid and calculating each number based on its position in the grid, then flattening it to a 1D array.

import numpy as np

num=50
m=5
k=3

# coordinates in a grid of width k+1 and height m
y, x = np.mgrid[:m, :k+1]

# a=[[50-0, 50-1, 50-2, 50-3], [50-0-2*3*1, 50-1-2*3*1, ...], [50-0-2*3*2...]...]
a = num - x - 2 * k * y

print(a.ravel())

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.