Copy flat list of upper triangle entries to full matrix?

前端 未结 4 1325
礼貌的吻别
礼貌的吻别 2021-01-21 13:53

I have the upper triangle entries (including diagonal) of a symmetric matrix in a flat list (concatenated rows), and I want to use them to fill in the full matrix, including the

4条回答
  •  北恋
    北恋 (楼主)
    2021-01-21 14:23

    Here's my nomination for a faster, and possibly better, way to make a symmetric matrix from flat values:

    def make_sym(val, n):
        # uses boolean mask
        # uses the same lower tri as np.triu
        mask = ~np.tri(5,k=-1,dtype=bool)
        out = np.zeros((n,n),dtype=val.dtype)
        out[mask] = val
        out.T[mask] = val
        return out
    

    testing:

    In [939]: val=np.arange(1,16)
    In [940]: make_sym(val, 5)
    Out[940]: 
    array([[ 1,  2,  3,  4,  5],
           [ 2,  6,  7,  8,  9],
           [ 3,  7, 10, 11, 12],
           [ 4,  8, 11, 13, 14],
           [ 5,  9, 12, 14, 15]])
    

    Like the other answers it uses out.T[] to assign the lower triangle.

    Warren's answer uses np.triu_indices, which are the where values. This type of indexing is a bit slower than boolean masking.

    But as I noted the np.triu that Divakar uses does not return a boolean mask in earlier numpy versions (e.g. 1.9). This is what prompted me to dig into the issue.

    In 1.10 this function was rewritten as:

    mask = np.tri(*m.shape[-2:], k=k-1, dtype=bool)
    return np.where(mask, np.zeros(1, m.dtype), m)
    

    I gain a bit of speed by replacing the where with ~mask. Same result, but just cutting out an intermediate step.

提交回复
热议问题