1

I want to have something that could split an 1-D array :

np.array([600, 400, 300, 600, 100, 0, 2160])

into a 2-D array based on a value, e.g. 500 such that the resulting array should look like

500 | 100 | 0   | 0   | 0   
400 | 0   | 0   | 0   | 0   
300 | 0   | 0   | 0   | 0   
500 | 100 | 0   | 0   | 0   
100 | 0   | 0   | 0   | 0   
0   | 0   | 0   | 0   | 0   
500 | 500 | 500 | 500 | 160

where we fill from the left with how many 500's there could be and the last one as a reminder.

I am thinking of using np.divmod() but have no idea how to structure the array itself.

2
  • Can you expand on whats happening in your calculation of the result? Commented May 20, 2021 at 11:56
  • So for first number 600 = 500 * 1 + 100 so I want to have, for the first row, 500 100 for the second number 400 = 500 * 0 + 400 so I want to have, for the second row, only one number 400 and so on Commented May 20, 2021 at 11:59

2 Answers 2

6

It's a min/max problem not division.

import numpy as np

arr = np.array([600, 400, 300, 600, 100, 0, 2160 ])    
res = np.zeros( (7, 6), dtype = np.int64)
res[:] = arr[:,None]

res -= np.arange( 0, 3000, 500 ) # Subtract successive 500s from arr.

res = np.clip( res, 0, 500 ) # Clip results to lie >= 0 and <= 500

res 

# array([[500, 100,   0,   0,   0,   0],
#        [400,   0,   0,   0,   0,   0],
#        [300,   0,   0,   0,   0,   0],
#        [500, 100,   0,   0,   0,   0],
#        [100,   0,   0,   0,   0,   0],
#        [  0,   0,   0,   0,   0,   0],
#        [500, 500, 500, 500, 160,   0]])

Or as a one liner

np.clip( arr[:,None] - np.arange(0,3000,500), 0, 500 )

Following the Mad Physicist's comment below a more general function

def steps_of( arr, step ):
    temp = arr[:, None] - np.arange( 0, step * ( arr.max() // step + 1), step)
    return np.clip( temp, 0, step )


    
Sign up to request clarification or add additional context in comments.

1 Comment

Part of the challenge is computing 6 and 3000 based on arr rather than hard coding them. Also, OP has 5 columns, not 6. I'd suggest doing something like m = arr.shape[0], n = np.ceil(arr.max() / 500).astype(int), res = np.zeros_like(arr, shape=(m, n)) - 500 * np.arange(n)
1

One other solution, with the same logic than @TlsChris's answer, using np.cumsum() and broadcasting:

# Divisor
n = 500
# Input data in 2D.
x = np.array([[600, 400, 300, 600, 100, 0, 2160]])
# Dimension of the output array (here : (7,5))
d = (len(x[0]),x.max()//n+1) 
# Compute the result
r = np.clip(x.T*np.ones((1,d[1]))-np.cumsum(np.ones(d)*n,1)+n,0,n)

The last line simply compute:

#array([[ 600.,  600.,  600.,  600.,  600.],        array([[1000., 1500., 2000., 2500., 3000.],
#       [ 400.,  400.,  400.,  400.,  400.],               [1000., 1500., 2000., 2500., 3000.],
#       [ 300.,  300.,  300.,  300.,  300.],               [1000., 1500., 2000., 2500., 3000.],
#       [ 600.,  600.,  600.,  600.,  600.],      -        [1000., 1500., 2000., 2500., 3000.],  
#       [ 100.,  100.,  100.,  100.,  100.],               [1000., 1500., 2000., 2500., 3000.],
#       [   0.,    0.,    0.,    0.,    0.],               [1000., 1500., 2000., 2500., 3000.],
#       [2160., 2160., 2160., 2160., 2160.]])              [1000., 1500., 2000., 2500., 3000.]])

And then apply the np.clip() function

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.