【问题标题】:How to multiply a numpy tuple array by scalar array如何将 numpy 元组数组乘以标量数组
【发布时间】:2011-07-04 15:04:40
【问题描述】:

我有一个形状为 (N,2) 的 numpy 数组 A 和一个形状为 (N) 的 numpy 数组 S。

如何将两个数组相乘?目前我正在使用此代码:

tupleS = numpy.zeros( (N , 2) )
tupleS[:,0] = S
tupleS[:,1] = S
product = A * tupleS

我是 python 初学者。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: python arrays numpy tuples


    【解决方案1】:

    Numpy 使用行优先顺序,因此您必须显式创建一列。如:

    >> A = numpy.array(range(10)).reshape(5, 2)
    >>> B = numpy.array(range(5))
    >>> B
    array([0, 1, 2, 3, 4])
    >>> A * B
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: shape mismatch: objects cannot be broadcast to a single shape
    >>> B = B.reshape(5, 1)
    >>> B
    array([[0],
           [1],
           [2],
           [3],
           [4]])
    >>> A * B
    array([[ 0,  0],
           [ 2,  3],
           [ 8, 10],
           [18, 21],
           [32, 36]])
    

    【讨论】:

    • 值得注意的是reshape 创建的是视图,而不是副本:&gt;&gt;&gt; s = numpy.arange(5); s.reshape(5, 1)[3,0] = 99; repr(s) -> 'array([ 0, 1, 2, 99, 4])'。所以你可以只做A * B.reshape(5, 1)而不改变B
    【解决方案2】:

    与@senderle 的答案基本相同,但不需要对 S 进行就地操作。您可以通过添加索引为 None 的轴的方式获得一个数组切片,这将使它们相乘:@987654322 @。

    >>> S = np.arange(5)
    >>> S
    array([0, 1, 2, 3, 4])
    >>> A = np.arange(10).reshape((5,2))
    >>> A
    array([[0, 1],
           [2, 3],
           [4, 5],
           [6, 7],
           [8, 9]])
    >>> S[:,None]
    array([[0],
           [1],
           [2],
           [3],
           [4]])
    >>> A * S[:,None]
    array([[ 0,  0],
           [ 2,  3],
           [ 8, 10],
           [18, 21],
           [32, 36]])
    

    【讨论】:

      【解决方案3】:

      你试过这个吗:

      product = A * S
      

      【讨论】:

      • +1,使用 numpy 的广播功能总是要走的路。
      • @Stiefel,@MRAB,我认为问题在于您必须为broadcasting to work 重塑S
      • 对,由于形状不匹配,A*S 不起作用。重塑确实是解决方案。
      【解决方案4】:

      你的问题的标题有点用词不当,我认为你遇到的问题主要与numpybroadcasting rules有关。因此,以下内容将不起作用(正如您已经观察到的那样):

      In []: N= 5
      In []: A= rand(N, 2)
      In []: A.shape
      Out[]: (5, 2)
      
      In []: S= rand(N)
      In []: S.shape
      Out[]: (5,)
      
      In []: A* S
      ------------------------------------------------------------
      Traceback (most recent call last):
        File "<ipython console>", line 1, in <module>
      ValueError: operands could not be broadcast together with shapes (5,2) (5) 
      

      然而,现在使S 与广播规则(A* S 的元素明智产品)兼容的一种简单方法是扩展其维度,例如:

      In []: A* S[:, None]
      Out[]: 
      array([[ 0.54216549,  0.04964989],
             [ 0.41850647,  0.4197221 ],
             [ 0.03790031,  0.76744563],
             [ 0.29381325,  0.53480765],
             [ 0.0646535 ,  0.07367852]])
      

      但这实际上只是expand_dims 的语法糖,例如:

      In []: expand_dims(S, 1).shape
      Out[]: (5, 1)
      

      无论如何,我个人更喜欢这种简单无忧的方法:

      In []: S= rand(N, 1)
      In []: S.shape
      Out[]: (5, 1)
      
      In []: A* S
      Out[]: 
      array([[ 0.40421854,  0.03701712],
             [ 0.63891595,  0.64077179],
             [ 0.03117081,  0.63117954],
             [ 0.24695035,  0.44950641],
             [ 0.14191946,  0.16173008]])
      

      因此python;显式比隐式更直接。

      【讨论】:

      • 谢谢,我改了标题。好答案。我接受了 senderles 的回答,因为它是最简单的。所有答案都旨在将形状修改为 (N,1)。
      【解决方案5】:

      我能想到:

      product = A * numpy.tile(S, (2,1)).T
      

      更快的解决方案可能是:

      product = [d * S for d in A.T]
      

      虽然这不会为您提供一个 numpy 数组作为输出,但它已被转置。所以要得到一个类似的numpy数组(注意这比第一种解决方案要慢):

      product = numpy.array([d * S for d in A.T]).T
      

      可能还有十几种其他有效的解决方案,包括比这些更好的解决方案......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-17
        • 1970-01-01
        • 2013-01-08
        • 2021-12-15
        • 2010-12-19
        • 1970-01-01
        • 2017-12-12
        • 1970-01-01
        相关资源
        最近更新 更多