Search code examples
pythonnumpymultidimensional-arrayvectorizationmasking

Python/Numpy: Vectorizing repeated row insertion in a 2D array


Is it possible to vectorize the insertion of rows?

I have a large 2D numpy array arr (below) and a list of indices. For each index of arr in indices I would like to insert the row at that index back into arr row 5 times at that same index.

indices = [2, 4, 5, 9, 11, 12, 16, 18, 19]  

Currently I'm just looping through all the indices and inserting new rows. This approach is slow for a large list of thousands of rows, so for performance reasons I'm wondering is it possible to vectorize this multi-point tile-type insertion?

arr = [       
        [' ', ' ', 'd'],
        [' ', 'd', ' '],
        [' ', 'd', 'd'],    # <-- reinsert arr[2] here 5 times
        ['d', ' ', ' '],
        ['d', ' ', 'd'],    # <-- reinsert arr[4] here 5 times
        ['d', 'd', ' '],    # <-- reinsert arr[5] here 5 times
        ['d', 'd', 'd'],
        [' ', ' ', 'e'],
        [' ', 'e', ' '],
        [' ', 'e', 'e'],    # <-- reinsert arr[9] here 5 times
        ['e', ' ', ' '],
        ['e', ' ', 'e'],    # <-- reinsert arr[11] here 5 times
        ['e', 'e', ' '],    # <-- reinsert arr[12] here 5 times
        ['e', 'e', 'e'],
        [' ', ' ', 'f'],
        [' ', 'f', ' '],
        [' ', 'f', 'f'],    # <-- reinsert arr[16] here 5 times
        ['f', ' ', ' '],
        ['f', ' ', 'f'],    # <-- reinsert arr[18] here 5 times
        ['f', 'f', ' ']     # <-- reinsert arr[19] here 5 times
    ]

Example of first insertion of desired result:

arr = [       
        [' ', ' ', 'd'],
        [' ', 'd', ' '],
        [' ', 'd', 'd'],    # <-- arr[2]
        [' ', 'd', 'd'],    # <-- new insert
        [' ', 'd', 'd'],    # <-- new insert
        [' ', 'd', 'd'],    # <-- new insert
        [' ', 'd', 'd'],    # <-- new insert
        [' ', 'd', 'd'],    # <-- new insert
        ['d', ' ', ' ']
        #...
      ]

Solution

  • You could use np.repeat for this:

    indices = [2, 4, 5, 9, 11, 12, 16, 18, 19]
    rpt = np.ones(len(arr), dtype=int)
    rpt[indices] = 5
    
    np.repeat(arr, rpt, axis=0)