【问题标题】:Numpy: Divide each row by a vector elementNumpy:将每一行除以一个向量元素
【发布时间】:2013-11-05 07:12:42
【问题描述】:

假设我有一个 numpy 数组:

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

我有一个对应的“向量:”

vector = np.array([1,2,3])

我如何对每一行的data 进行减法或除法运算,结果是:

sub_result = [[0,0,0], [0,0,0], [0,0,0]]
div_result = [[1,1,1], [1,1,1], [1,1,1]]

长话短说:如何使用与每一行对应的一维标量数组对二维数组的每一行执行操作?

【问题讨论】:

  • 如果我有一个 3x1000 数组并尝试除以 3-elt 数组,我得到一个错误。为什么这不起作用?

标签: python arrays numpy scipy


【解决方案1】:

给你。您只需将None(或np.newaxis)与广播结合使用:

In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

【讨论】:

  • here 是文档。
  • @user108569 使用最新版本的 numpy (1.18.1),None 仍然等效于 np.newaxis。我不确定您的设置是什么,或者您遇到的确切问题,但答案仍然有效。
【解决方案2】:

如前所述,使用Nonenp.newaxes 进行切片是实现此目的的好方法。 另一种选择是使用转置和广播,如

(data.T - vector).T

(data.T / vector).T

对于更高维数组,您可能需要使用 NumPy 数组的 swapaxes 方法或 NumPy rollaxis 函数。 确实有很多方法可以做到这一点。

有关广播的更完整说明,请参阅 http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

【讨论】:

    【解决方案3】:

    补充stackoverflowuser2010的答案,一般情况下你可以直接使用

    data = np.array([[1,1,1],[2,2,2],[3,3,3]])
    
    vector = np.array([1,2,3])
    
    data / vector.reshape(-1,1)
    

    这会将您的向量变成column matrix/vector。允许您根据需要进行元素操作。至少对我来说,这是最直观的方式,因为(在大多数情况下)numpy 只会使用相同内部存储器的视图来进行整形,它也很有效。

    【讨论】:

    • 这应该是公认的答案。使用.reshape(-1,1) 创建列向量是使用广播最直观的方式。
    【解决方案4】:

    Pythonic 的方法是……

    np.divide(data.T,vector).T
    

    这会处理整形,结果也是浮点格式。 在其他答案中,结果采用四舍五入的整数格式。

    #NOTE:数据和向量中的列数应匹配

    【讨论】:

    • 注意:这不符合 OP 的要求。最终结果是数组([[1., 0.5, 0.33333333], [2., 1., 0.66666667], [3., 1.5, 1. ]])。它可能是“Pythonic”,但它不正确。
    • @MarkCramer 谢谢。我已更正我的答案以提供正确的结果。
    • 这是正确的,但不再是pythonic。奇怪的是 numpy 如此优雅,但这样的事情就像......嗯?
    【解决方案5】:

    JoshAdel 的解决方案使用 np.newaxis 添加维度。另一种方法是使用reshape() to align the dimensions in preparation for broadcasting

    data = np.array([[1,1,1],[2,2,2],[3,3,3]])
    vector = np.array([1,2,3])
    
    data
    # array([[1, 1, 1],
    #        [2, 2, 2],
    #        [3, 3, 3]])
    vector
    # array([1, 2, 3])
    
    data.shape
    # (3, 3)
    vector.shape
    # (3,)
    
    data / vector.reshape((3,1))
    # array([[1, 1, 1],
    #        [1, 1, 1],
    #        [1, 1, 1]])
    

    执行 reshape() 允许尺寸排列以进行广播:

    data:            3 x 3
    vector:              3
    vector reshaped: 3 x 1
    

    请注意,data/vector 可以,但它不会为您提供所需的答案。它将array 的每个(而不是每个)除以vector 的每个对应元素。如果您将 vector 明确地改造成 1x3 而不是 3x1,这就是您将得到的结果。

    data / vector
    # array([[1, 0, 0],
    #        [2, 1, 0],
    #        [3, 1, 1]])
    data / vector.reshape((1,3))
    # array([[1, 0, 0],
    #        [2, 1, 0],
    #        [3, 1, 1]])
    

    【讨论】:

      【解决方案6】:

      关键是将大小为 (3,) 的向量重塑为 (3,1):将每一行除以一个元素或 (1,3):将每一列除以一个元素。由于 data.shape 与 vector.shape 不对应,NumPy 会自动将 vector 的形状扩展为 (3,3) 并按元素进行除法。

      In[1]: data/vector.reshape(-1,1)
      Out[1]:
      array([[1., 1., 1.],
             [1., 1., 1.],
             [1., 1., 1.]])
      
      In[2]: data/vector.reshape(1,-1)
      Out[2]:
      array([[1.        , 0.5       , 0.33333333],
             [2.        , 1.        , 0.66666667],
             [3.        , 1.5       , 1.        ]])
      
      

      类似的:

      x = np.arange(9).reshape(3,3)
      x
      array([[0, 1, 2],
             [3, 4, 5],
             [6, 7, 8]])
      
      x/np.sum(x, axis=0, keepdims=True)
      array([[0.        , 0.08333333, 0.13333333],
             [0.33333333, 0.33333333, 0.33333333],
             [0.66666667, 0.58333333, 0.53333333]])
      
      x/np.sum(x, axis=1, keepdims=True)
      array([[0.        , 0.33333333, 0.66666667],
             [0.25      , 0.33333333, 0.41666667],
             [0.28571429, 0.33333333, 0.38095238]])
      
      print(np.sum(x, axis=0).shape)
      print(np.sum(x, axis=1).shape)
      print(np.sum(x, axis=0, keepdims=True).shape)
      print(np.sum(x, axis=1, keepdims=True).shape)
      (3,)
      (3,)
      (1, 3)
      (3, 1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多