Multiplying across in a numpy array

前端 未结 6 898
借酒劲吻你
借酒劲吻你 2020-11-28 03:41

I\'m trying to multiply each of the terms in a 2D array by the corresponding terms in a 1D array. This is very easy if I want to multiply every column by the 1D array, as sh

相关标签:
6条回答
  • 2020-11-28 04:01

    I've compared the different options for speed and found that – much to my surprise – all options (except diag) are equally fast. I personally use

    A * b[:, None]
    

    (or (A.T * b).T) because it's short.


    Code to reproduce the plot:

    import numpy
    import perfplot
    
    
    def newaxis(data):
        A, b = data
        return A * b[:, numpy.newaxis]
    
    
    def none(data):
        A, b = data
        return A * b[:, None]
    
    
    def double_transpose(data):
        A, b = data
        return (A.T * b).T
    
    
    def double_transpose_contiguous(data):
        A, b = data
        return numpy.ascontiguousarray((A.T * b).T)
    
    
    def diag_dot(data):
        A, b = data
        return numpy.dot(numpy.diag(b), A)
    
    
    def einsum(data):
        A, b = data
        return numpy.einsum("ij,i->ij", A, b)
    
    
    perfplot.save(
        "p.png",
        setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
        kernels=[
            newaxis,
            none,
            double_transpose,
            double_transpose_contiguous,
            diag_dot,
            einsum,
        ],
        n_range=[2 ** k for k in range(13)],
        xlabel="len(A), len(b)",
    )
    
    0 讨论(0)
  • 2020-11-28 04:06

    Why don't you just do

    >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> c = np.array([0,1,2])
    >>> (m.T * c).T
    

    ??

    0 讨论(0)
  • 2020-11-28 04:08

    Normal multiplication like you showed:

    >>> import numpy as np
    >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> c = np.array([0,1,2])
    >>> m * c
    array([[ 0,  2,  6],
           [ 0,  5, 12],
           [ 0,  8, 18]])
    

    If you add an axis, it will multiply the way you want:

    >>> m * c[:, np.newaxis]
    array([[ 0,  0,  0],
           [ 4,  5,  6],
           [14, 16, 18]])
    

    You could also transpose twice:

    >>> (m.T * c).T
    array([[ 0,  0,  0],
           [ 4,  5,  6],
           [14, 16, 18]])
    
    0 讨论(0)
  • 2020-11-28 04:21

    You could also use matrix multiplication (aka dot product):

    a = [[1,2,3],[4,5,6],[7,8,9]]
    b = [0,1,2]
    c = numpy.diag(b)
    
    numpy.dot(c,a)
    

    Which is more elegant is probably a matter of taste.

    0 讨论(0)
  • 2020-11-28 04:21

    Yet another trick (as of v1.6)

    A=np.arange(1,10).reshape(3,3)
    b=np.arange(3)
    
    np.einsum('ij,i->ij',A,b)
    

    I'm proficient with the numpy broadcasting (newaxis), but I'm still finding my way around this new einsum tool. So I had play around a bit to find this solution.

    Timings (using Ipython timeit):

    einsum: 4.9 micro
    transpose: 8.1 micro
    newaxis: 8.35 micro
    dot-diag: 10.5 micro
    

    Incidentally, changing a i to j, np.einsum('ij,j->ij',A,b), produces the matrix that Alex does not want. And np.einsum('ji,j->ji',A,b) does, in effect, the double transpose.

    0 讨论(0)
  • 2020-11-28 04:22

    For those lost souls on google, using numpy.expand_dims then numpy.repeat will work, and will also work in higher dimensional cases (i.e. multiplying a shape (10, 12, 3) by a (10, 12)).

    >>> import numpy
    >>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> b = numpy.array([0,1,2])
    >>> b0 = numpy.expand_dims(b, axis = 0)
    >>> b0 = numpy.repeat(b0, a.shape[0], axis = 0)
    >>> b1 = numpy.expand_dims(b, axis = 1)
    >>> b1 = numpy.repeat(b1, a.shape[1], axis = 1)
    >>> a*b0
    array([[ 0,  2,  6],
       [ 0,  5, 12],
       [ 0,  8, 18]])
    >>> a*b1
    array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])
    
    0 讨论(0)
提交回复
热议问题