Numpy repeat for 2d array

arrays, numpy, python, vectorization

Solution

So you have a different repeat array for each row? But the total number of repeats per row is the same?

Just do the `repeat` on the flattened arrays, and reshape back to the correct number of rows.

In [529]: np.repeat(arr,rep.flat)
Out[529]: array([10, 10, 10, 24, 24, 24, 24, 10, 10, 24, 24, 24, 24,  1])
In [530]: np.repeat(arr,rep.flat).reshape(2,-1)
Out[530]: 
array([[10, 10, 10, 24, 24, 24, 24],
       [10, 10, 24, 24, 24, 24,  1]])

If the repetitions per row vary, we have the problem of padding variable length rows. That's come up in other SO questions. I don't recall all the details, but I think the solution is along this line:

Change `rep` so the numbers differ:

In [547]: rep
Out[547]: 
array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0],
       [2, 2, 2, 1, 0, 2, 0, 0, 0, 0]])
In [548]: lens=rep.sum(axis=1)
In [549]: lens
Out[549]: array([7, 9])
In [550]: m=np.max(lens)
In [551]: m
Out[551]: 9

create the target:

In [552]: res = np.zeros((arr.shape[0],m),arr.dtype)

create an indexing array - details need to be worked out:

In [553]: idx=np.r_[0:7,m:m+9]
In [554]: idx
Out[554]: array([ 0,  1,  2,  3,  4,  5,  6,  9, 10, 11, 12, 13, 14, 15, 16, 17])

flat indexed assignment:

In [555]: res.flat[idx]=np.repeat(arr,rep.flat)
In [556]: res
Out[556]: 
array([[10, 10, 10, 24, 24, 24, 24,  0,  0],
       [10, 10, 24, 24, 24, 24,  1,  1,  1]])

Problem

Given two arrays, say ``` arr = array([10, 24, 24, 24, 1, 21, 1, 21, 0, 0], dtype=int32) rep = array([3, 2, 2, 0, 0, 0, 0, 0, 0, 0], dtype=int32) ``` np.repeat(arr, rep) returns ``` array([10, 10, 10, 24, 24, 24, 24], dtype=int32) ``` Is there any way to replicate this functionality for a set of 2D arrays? That is given ``` arr = array([[10, 24, 24, 24, 1, 21, 1, 21, 0, 0], [10, 24, 24, 1, 21, 1, 21, 32, 0, 0]], dtype=int32) rep = array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 0, 0, 0, 0, 0, 0, 0]], dtype=int32) ``` is it possible to create a function which vectorizes? PS: The number of repeats in each row need not be the same. I'm padding each result row to ensure that they are of same size. ``` def repeat2d(arr, rep): # Find the max length of repetitions in all the rows. max_len = rep.sum(axis=-1).max() # Create a common array to hold all results. Since each repeated array will have # different sizes, some of them are padded with zero. ret_val = np.empty((arr.shape[0], maxlen)) for i in range(arr.shape[0]): # Repeated array will not have same num of cols as ret_val. temp = np.repeat(arr[i], rep[i]) ret_val[i,:temp.size] = temp return ret_val ``` I do know about np.vectorize and I know that it does not give any performance benefits over the normal version.

Original source