Fill non rectangular slice of numpy array

In [134]: mat = np.array([
     ...:     [0, 4, 4, 4, 4],
     ...:     [1, 4, 4, 4, 4],
     ...:     [3, 4, 5, 6, 6],
     ...:     [2, 4, 5, 5, 5],
     ...: ])
     ...: 
In [135]: index = mat[:, 0]+1          # add the 1 here
In [136]: for i,v in enumerate(index):
     ...:     mat[i,v:] = mat[i,v]
     ...: 
     ...: 
In [137]: mat
Out[137]: 
array([[0, 4, 4, 4, 4],
       [1, 4, 4, 4, 4],
       [3, 4, 5, 6, 6],
       [2, 4, 5, 5, 5]])

construct a boolean mask (as suggested for padding problems)

In [141]: np.arange(5)>=index[:,None]
Out[141]: 
array([[False,  True,  True,  True,  True],
       [False, False,  True,  True,  True],
       [False, False, False, False,  True],
       [False, False, False,  True,  True]])

This is True where we want to fill in values. But the next trick is to create an array of values like this:

In [142]: mat[_]
Out[142]: array([4, 4, 4, 4, 4, 4, 4, 6, 5, 5])

We get the number of fills per row with a sum:

In [143]: mask = np.arange(5)>=index[:,None]
In [144]: mask.sum(axis=1)
Out[144]: array([4, 3, 1, 2])

And get the fill array by using those to repeat the selected row value:

In [148]: mat[np.arange(4),index].repeat(mask.sum(axis=1))
Out[148]: array([4, 4, 4, 4, 4, 4, 4, 6, 5, 5])
In [149]: mat[mask] = _

Decide for yourself whether that "vectorized" approach is worth your time.