代码之家  ›  专栏  ›  技术社区  ›  HolyCrack

如何使用numpy的效率来计算一个矩阵,该矩阵是向量与其每个值的相减?[副本]

  •  0
  • HolyCrack  · 技术社区  · 7 年前

    我有这个向量

    X=numpy.array([1,2,3,4])
    

    我想要这个矩阵:

    difX=([0,1,2,3],[-1,0,1,2],[-2,-1,0,1],[-3,-2,-1,0])
    

    编程此嵌套循环的简单方法是:

    import numpy as np
    
    X=numpy.array([1,2,3,4])
    S=X.shape[0]
    difx=np.empty((S,S))
    
    for i in range(S):
    
        Xi=X[i]
    
        for j in range(S):
    
            Xj=X[j]
            difx[i,j]= Xi-Xj
    

    然而,我有一个非常大的向量,我不想使用任何循环。我想使用numpy的阵列模块的效率。

    非常感谢。

    3 回复  |  直到 7 年前
        1
  •  2
  •   Paul Panzer    7 年前

    有几种可能性:

    >>> X-X[:,None]
    array([[ 0,  1,  2,  3],
           [-1,  0,  1,  2],
           [-2, -1,  0,  1],
           [-3, -2, -1,  0]])
    >>> numpy.add.outer(-X, X)
    array([[ 0,  1,  2,  3],
           [-1,  0,  1,  2],
           [-2, -1,  0,  1],
           [-3, -2, -1,  0]])
    >>> numpy.subtract(*reversed(numpy.ix_(X, X)))
    array([[ 0,  1,  2,  3],
           [-1,  0,  1,  2],
           [-2, -1,  0,  1],
           [-3, -2, -1,  0]])
    >>> numpy.subtract.outer(X, X).T
    array([[ 0,  1,  2,  3],
           [-1,  0,  1,  2],
           [-2, -1,  0,  1],
           [-3, -2, -1,  0]])
    

    可能是最短的(假设 numpy 导入为 np ):

    >>> X-np.c_[X]
    array([[ 0,  1,  2,  3],
           [-1,  0,  1,  2],
           [-2, -1,  0,  1],
           [-3, -2, -1,  0]])
    

    时间安排:

    >>> from timeit import timeit
    >>> kwds = dict(globals=globals(), number=100000)
    >>> 
    >>> timeit("numpy.add.outer(-X, X)", **kwds)
    0.2078194150235504
    >>> timeit("numpy.subtract.outer(X, X).T", **kwds)
    0.1835216749459505
    >>> timeit("X-X[:,None]", **kwds)
    0.16011965298093855
    >>> timeit("X-np.c_[X]", **kwds)
    0.9050748841837049
    >>> timeit("numpy.subtract(*reversed(numpy.ix_(X, X)))", **kwds)
    0.7874130869749933
    >>> timeit("X-X[None].T", **kwds)
    0.1729387198574841
    >>> timeit("X-X.reshape(-1,1)", **kwds)
    0.16520787891931832
    

    对于较大的 X 这些差异变得微不足道:

    X = np.repeat(X, 100)
    >>> kwds = dict(globals=globals(), number=1000)
    >>>
    >>> timeit("X-np.atleast_2d(X).T", **kwds)
    0.20351033308543265
    >>> timeit("numpy.add.outer(-X, X)", **kwds)
    0.20114074111916125
    >>> timeit("numpy.subtract.outer(X, X).T", **kwds)
    0.19854155299253762
    >>> timeit("numpy.subtract(*reversed(numpy.ix_(X, X)))", **kwds)
    0.20600174297578633
    >>> timeit("X-np.c_[X]", **kwds)
    0.2087497659958899
    >>> timeit("X-X[:,None]", **kwds)
    0.20137557992711663
    >>> timeit("X-X[None].T", **kwds)
    0.19664623402059078
    >>> timeit("X-X.reshape(-1,1)", **kwds)
    0.201627325033769
    
        2
  •  2
  •   Julien    7 年前

    只需使用广播和新轴:

    X[None,:]-X[:,None] 
    
        3
  •  1
  •   TwistedSim    7 年前

    我没有测试速度差,但这应该可以:

    import numpy as np
    import numpy.matlib
    
    X = np.array([1,2,3,4])
    
    print(np.matlib.repmat(X, 4, 1) - np.matlib.repmat(X.reshape(4,1), 1, 4))