Numpy repeat for 2d array
<p>Given two arrays, say </p>

<pre><code>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)
</code></pre>

<p>np.repeat(arr, rep) returns </p>

<pre><code>array([10, 10, 10, 24, 24, 24, 24], dtype=int32)
</code></pre>

<p>Is there any way to replicate this functionality for a set of 2D arrays?</p>

<p>That is given </p>

<pre><code>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)
</code></pre>

<p>is it possible to create a function which vectorizes?</p>

<p>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.</p>

<pre><code>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 
</code></pre>

<p>I do know about np.vectorize and I know that it does not give any performance benefits over the normal version.</p>

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

<p>Just do the <code>repeat</code> on the flattened arrays, and reshape back to the correct number of rows.</p>

<pre><code>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]])
</code></pre>

<p>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:</p>

<p>Change <code>rep</code> so the numbers differ:</p>

<pre><code>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
</code></pre>

<p>create the target:</p>

<pre><code>In [552]: res = np.zeros((arr.shape[0],m),arr.dtype)
</code></pre>

<p>create an indexing array - details need to be worked out:</p>

<pre><code>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])
</code></pre>

<p>flat indexed assignment:</p>

<pre><code>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]])
</code></pre>

python arrays numpy vectorization