【问题标题】:Python: NumPy divide line by sum or replace it by anotherPython:NumPy 除以总和或将其替换为另一个
【发布时间】:2021-03-13 14:51:40
【问题描述】:

我目前正在尝试使用 NumPy 库获取矩阵,但有一个问题我找不到解决方案

我目前有以下 numpy 数组

mat = 
[[0. 1. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0.]
 [1. 1. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1. 1.]
 [0. 0. 0. 1. 0. 1.]
 [0. 0. 0. 1. 0. 0.]]

现在我想将每一行除以行的总和,但如果行的总和等于 0,我将其替换为 1/len(mat) 的行。我尝试使用以下代码:

    for line in mat:
        line /= np.sum(line)
        mat[np.isnan(mat)] = 1/N 

以下代码将返回:

[[0.         0.5        0.5        0.         0.         0.        ]
 [0.16666667 0.16666667 0.16666667 0.16666667 0.16666667 0.16666667]
 [0.33333333 0.33333333 0.         0.         0.33333333 0.        ]
 [0.         0.         0.         0.         0.5        0.5       ]
 [0.         0.         0.         0.5        0.         0.5       ]
 [0.         0.         0.         1.         0.         0.        ]]

这是我试图得到的正确结果,但它给出了RuntimeWarning: invalid value encountered in true_divide

所以我想知道是否有更好的方法来获得正确的结果,所以我不必在每一行之后检查该行是否充满nan。 (此外,如果有一种方法可以立即将每行除以每行的总和,而不必使用for 循环。)

【问题讨论】:

    标签: python arrays numpy matrix


    【解决方案1】:

    逐行除以总和并用1/len(mat)填充NaN

    np.nan_to_num(                     # Function to replace non-finite values with given value
        np.divide(                     # Divide function
            mat,                       # Input array for division
            mat.sum(axis=1)[:, None]   # Sum across axis=1(across row) and transpose them for division
        ),
        nan=1/len(mat)                 # value that will replace non-finite values
    )
    

    单线

    np.nan_to_num(np.divide(mat, mat.sum(axis=1)[:, None]), nan=1/len(mat))
    

    输出

    [[0.         0.5        0.5        0.         0.         0.        ]
     [0.16666667 0.16666667 0.16666667 0.16666667 0.16666667 0.16666667]
     [0.33333333 0.33333333 0.         0.         0.33333333 0.        ]
     [0.         0.         0.         0.         0.5        0.5       ]
     [0.         0.         0.         0.5        0.         0.5       ]
     [0.         0.         0.         1.         0.         0.        ]]
    

    【讨论】:

    • 太棒了!但是,是否有可能获得“详细版本”。我是 one-liners 的忠实粉丝,但由于我从未真正使用过 numpy,我很难理解
    • @needle 已按功能说明添加功能
    • 谢谢你,我只是想知道,但你的代码也给了RuntimeWarning: invalid value encountered in true_divide。这真的不是问题吗?或者他们可能是一种简单的解决方法?
    • @needle 当您除以零时,它会创建一个 inf(无穷大)值。 Numpy 只是警告您,以便您意识到这一点。如果您不希望它弹出,您可以使用np.seterr(divide='ignore', invalid='ignore') 禁用它。但有时它在非预期时会有所帮助。
    【解决方案2】:

    你在寻找类似的东西

    import numpy as np
    
    mat = np.array([[0. ,1. ,1., 0., 0., 0.],
     [0., 0., 0., 0., 0. ,0.],
     [1. ,1., 0., 0., 1., 0.],
     [0., 0., 0., 0. ,1., 1.],
     [0. ,0., 0., 1., 0., 1.],
     [0. ,0. ,0. ,1. ,0., 0.]])
    
    sum_ = np.sum(mat, axis=1)
    
    mat[(sum_==0), :] = 1/len(mat) # handle where sum==0
    mat[~(sum_==0), :] /= sum_[~(sum_==0), np.newaxis] # handle where sum not 0
    
    mat
    
    array([[0.        , 0.5       , 0.5       , 0.        , 0.        ,
            0.        ],
           [0.16666667, 0.16666667, 0.16666667, 0.16666667, 0.16666667,
            0.16666667],
           [0.33333333, 0.33333333, 0.        , 0.        , 0.33333333,
            0.        ],
           [0.        , 0.        , 0.        , 0.        , 0.5       ,
            0.5       ],
           [0.        , 0.        , 0.        , 0.5       , 0.        ,
            0.5       ],
           [0.        , 0.        , 0.        , 1.        , 0.        ,
            0.        ]])
    

    【讨论】:

      【解决方案3】:
      import numpy as np
      
      mat = np.array([[1,2,3],[4,5,6], [-1,0,1]])
      s = mat.sum(axis=1, keepdims=True)  # sum of each line
      out = np.ones_like(mat).astype(np.float) / len(mat)  # initialize with 1/N
      not_zeros = s[:,0]!=0  # logical indexes of noz zero sum lines 
      out[not_zeros, :] = mat[not_zeros, :] / s[not_zeros] # normalize onlt the non zero sum lines
      print(out)
      
      [[0.16666667 0.33333333 0.5       ]
       [0.26666667 0.33333333 0.4       ]
       [0.33333333 0.33333333 0.33333333]]
      

      更新 - 零和线是 1/N

      【讨论】:

      • 您的方法似乎只能部分工作,因为我希望它能够将任何用全零填充的行替换为由1/len(mat) 填充的行。我尝试在 numpy 数组 mat = [[0. 1. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 0.] [1. 1. 0. 0. 1. 0.] [0. 0. 0. 0. 1. 1.] [0. 0. 0. 1. 0. 1.] [0. 0. 0. 1. 0. 0.]] 上使用您的代码。它几乎可以工作,除了用零填充的行
      猜你喜欢
      • 2021-12-03
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-20
      • 1970-01-01
      • 1970-01-01
      • 2022-11-22
      • 2013-10-13
      相关资源
      最近更新 更多