Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill in numbers in a numpy array in sets of 1024

I have a large numpy array with increasing elements as follows

A = [512,2560,3584,5632,....]

Elements are always spaced at least 1024 apart

Let's say I need to transform that above array to the one below, where for each element of the original matrix A, I take a range of values from A[n] to A[n]+1024 (in steps of one) and those become the values of a new matrix as follows

A2 = [512,513,514,...,1535,2560,2561,2562,...3583,....]

The way I've set up the problem is to loop through the original matrix A, generate a range of values between A[0] and A[0]+1024 (for example), allocate them to a new array and so on. Code below. Convention is for A as the original seed matrix

seed = 0
A2 = np.empty(len(A)*1024,)
for ind in range(len(A)):
    A2[seed:seed+1024] = np.arange(A[ind],A[ind]+1024)
    seed = seed+1024;

I get the answer I need, but I'm wondering if that is the best way to do this. I'm a matlab user transitioning to using python and numpy, and I'm not used to optimizing numpy yet. I appreciate any help.

like image 894
turingsmachine Avatar asked Jan 27 '26 01:01

turingsmachine


2 Answers

You can use broadcasting -

(A[:,None] + np.arange(1024)).ravel()

Sample run -

# Input array
In [433]: A = np.array([512,2560,3584,5632])

# Add ranged numbers in a broadcasted way for elementwise addition   
In [434]: A[:,None] + np.arange(1024)
Out[434]: 
array([[ 512,  513,  514, ..., 1533, 1534, 1535],
       [2560, 2561, 2562, ..., 3581, 3582, 3583],
       [3584, 3585, 3586, ..., 4605, 4606, 4607],
       [5632, 5633, 5634, ..., 6653, 6654, 6655]])

# Finally flatten those for final output
In [435]: (A[:,None] + np.arange(1024)).ravel()
Out[435]: array([ 512,  513,  514, ..., 6653, 6654, 6655])

Alternatively with np.add.outer -

np.add.outer(A,range(1024)).ravel()

Equivalent MATLAB version :

For reference, the MATLAB version to leverage the equivalent broadcasting with bsxfun and keeping in mind the column-major ordering, would look something along these lines -

>> A = [512,2560,3584,5632];
>> sums = bsxfun(@plus, A, [0:1023].');
>> [sums(1:3,1) ; sums(end-2:end,1)].'
ans =
         512         513         514        1533        1534        1535
>> [sums(1:3,2) ; sums(end-2:end,2)].'
ans =
        2560        2561        2562        3581        3582        3583
>> [sums(1:3,3) ; sums(end-2:end,3)].'
ans =
        3584        3585        3586        4605        4606        4607
>> [sums(1:3,4) ; sums(end-2:end,4)].'
ans =
        5632        5633        5634        6653        6654        6655
>> out = reshape(sums,1,[]);
>> [out(1:3) out(end-2:end)]
ans =
         512         513         514        6653        6654        6655
like image 173
Divakar Avatar answered Jan 29 '26 14:01

Divakar


You can use:

(A.reshape(-1,1) + numpy.arange(1024)).reshape(-1)

This works as follows:

  1. first we use reshape(-1,1) to obtain an n×1 array;
  2. next we use broadcasting to add 0 to 1024 to every row; and
  3. then we reshape it back to a 1D array.
like image 25
Willem Van Onsem Avatar answered Jan 29 '26 15:01

Willem Van Onsem