【问题标题】:Make a numpy upper triangular matrix padded with Nan instead of zero制作一个用 Nan 而不是零填充的 numpy 上三角矩阵
【发布时间】:2015-10-09 02:53:41
【问题描述】:

我生成了一个 matplotlib 3d 曲面图。我只需要在绘图上看到矩阵的上三角形一半,因为另一半是多余的。

np.triu() 使矩阵的多余一半为零,但如果我可以将它们设为 Nans,我更愿意,那么这些单元格根本不会出现在表面图上。

用 NaN 而不是零填充的 Python 方法是什么?我不能用 NaN 搜索和替换 0,因为零会出现在我要显示的合法数据中。

【问题讨论】:

    标签: python numpy matplotlib


    【解决方案1】:

    您可以使用numpy.tril_indices()NaN 值分配给下三角形,例如:

    >>> import numpy as np
    >>> m = np.triu(np.arange(0, 12, dtype=np.float).reshape(4,3))
    >>> m
    array([[ 0.,  1.,  2.],
           [ 0.,  4.,  5.],
           [ 0.,  0.,  8.],
           [ 0.,  0.,  0.]])
    >>> m[np.tril_indices(m.shape[0], -1)] = np.nan
    >>> m
    array([[  0.,   1.,   2.],
           [ nan,   4.,   5.],
           [ nan,  nan,   8.],
           [ nan,  nan,  nan]])
    

    【讨论】:

    • 这是一个不错的解决方案,我喜欢它。
    【解决方案2】:

    tril_indices() 可能是这里生成较低三角形索引的明显方法,然后您可以使用这些方法将输入数组中的那些设置为 NaNs

    现在,如果您关心性能,您可以在创建这种下三角形状的蒙版后使用boolean indexing,然后将其设置为NaNs。实现看起来像这样 -

    m[np.arange(m.shape[0])[:,None] > np.arange(m.shape[1])] = np.nan
    

    所以,np.arange(m.shape[0])[:,None] > np.arange(m.shape[1]) 是这里使用 broadcasting 创建的掩码。

    示例运行 -

    In [51]: m
    Out[51]: 
    array([[ 11.,  49.,  23.,  30.],
           [ 40.,  41.,  19.,  26.],
           [ 32.,  36.,  30.,  25.],
           [ 15.,  27.,  25.,  40.],
           [ 33.,  18.,  45.,  43.]])
    
    In [52]: np.arange(m.shape[0])[:,None] > np.arange(m.shape[1]) # mask
    Out[52]: 
    array([[False, False, False, False],
           [ True, False, False, False],
           [ True,  True, False, False],
           [ True,  True,  True, False],
           [ True,  True,  True,  True]], dtype=bool)
    
    In [53]: m[np.arange(m.shape[0])[:,None] > np.arange(m.shape[1])] = np.nan
    
    In [54]: m
    Out[54]: 
    array([[ 11.,  49.,  23.,  30.],
           [ nan,  41.,  19.,  26.],
           [ nan,  nan,  30.,  25.],
           [ nan,  nan,  nan,  40.],
           [ nan,  nan,  nan,  nan]])
    

    运行时测试 -

    本部分将本解决方案中列出的基于布尔索引的方法与other solution 中基于np.tril_indices 的方法进行性能比较。

    In [38]: m = np.random.randint(10,50,(1000,1100)).astype(float)
    
    In [39]: %timeit m[np.tril_indices(m.shape[0], -1)] = np.nan
    10 loops, best of 3: 62.8 ms per loop
    
    In [40]: m = np.random.randint(10,50,(1000,1100)).astype(float)
    
    In [41]: %timeit m[np.arange(m.shape[0])[:,None] > np.arange(m.shape[1])] = np.nan
    100 loops, best of 3: 8.03 ms per loop
    

    【讨论】:

    • 哈,非常巧妙的解决方案。幸运的是我的矩阵很小,但是对于一个巨大的矩阵来说,很有意义。
    【解决方案3】:

    对于这个例子来说,形状或布局无关紧要,所以假设我们有一个二维数组 a 这样:

    >>> a
    array([[ 0.,  0.,  0.],
           [ 0.,  0.,  1.]])
    

    我们希望所有的 0 值都是 NaN。只需使用列表推导即可。

    >>> b = numpy.array([[i if i else numpy.nan for i in j] for j in a])
    >>> b
    array([[ nan,  nan,  nan],
           [ nan,  nan,   1.]])
    

    如果您有不为零的特定单元格,请在理解中指定它们。

    【讨论】:

    • 谢谢。不知道,到目前为止,我在 numpy 上遇到的所有事情都是,“如果它在进行迭代,那么你做的并不理想”。我怀疑这个问题会有更多的pythonic答案。
    猜你喜欢
    • 2010-12-14
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-01-21
    • 2018-09-20
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    相关资源
    最近更新 更多