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?
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]