pythonarraysnumpymatrix

Apply function for lower triangle of 2-d array


I have an array:

U = np.array([3, 5, 7, 9, 11])

I want to get a result like:

result = np.array([
    [  np.nan,      np.nan,      np.nan,      np.nan,    np.nan],
    [U[0] - U[1],   np.nan,      np.nan,      np.nan,    np.nan],
    [U[0] - U[2], U[1] - U[2],   np.nan,      np.nan,    np.nan],
    [U[0] - U[3], U[1] - U[3], U[2] - U[3],   np.nan,    np.nan],
    [U[0] - U[4], U[1] - U[4], U[2] - U[4], U[3] - U[4], np.nan]
])

I can use np.tril_indices(4, k=-1) to get indices of lower triangle without diagonal, but what is next?


Solution

  • A naive approach that does more work than necessary is to compute the entire difference and select the elements you need:

    np.where(np.arange(U.size)[:, None] > np.arange(U.size), U[:, None] - U, np.nan)
    

    This is one of the times where np.where is actually useful over a simple mask, although it can be done with a mask as well:

    result = np.full((U.size, U.size), np.nan)
    index = np.arange(U.size)
    mask = index[:, None] > index
    result[mask] = [U[:, None] - U][mask]
    

    A more efficient approach might be to use the indices more directly to index into the source:

    result = np.full((U.size, U.size), np.nan)
    r, c = np.tril_indices(U.size, k=-1)
    result[r, c] = U[c] - U[r]