如何计算2D numpy数组的所有列的总和(有效)

Pug*_*gie 48 python numpy

假设我有以下2D numpy数组,包括四行和三列:

>>> a = numpy.arange(12).reshape(4,3)
>>> print(a)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
Run Code Online (Sandbox Code Playgroud)

什么是生成包含所有列的总和的一维数组的有效方法(如[18, 22, 26])?这可以在不需要遍历所有列的情况下完成吗?

Joh*_*ard 91

查看文档numpy.sum,特别注意axis参数.总结列:

>>> import numpy as np
>>> a = np.arange(12).reshape(4,3)
>>> a.sum(axis=0)
array([18, 22, 26])
Run Code Online (Sandbox Code Playgroud)

或者,总结行:

>>> a.sum(axis=1)
array([ 3, 12, 21, 30])
Run Code Online (Sandbox Code Playgroud)

其他聚合函数一样numpy.mean,numpy.cumsum并且numpy.std,例如,也采取了axis参数.

来自暂定的Numpy教程:

许多一元操作,例如计算数组中所有元素的总和,都是作为ndarray类的方法实现的.默认情况下,这些操作适用于数组,就像它是一个数字列表一样,无论其形状如何.但是,通过指定axis 参数,您可以沿数组的指定轴应用操作:

  • 这是一个很好的答案.我通常更喜欢`a.sum(axis = 0)`到`a.sum(0)`.(我认为它更明确一点 - 这绝不是坏事) (3认同)
  • @Puggie,也许是"更通用"你的意思是"不使用内置的NumPy函数"?一般来说,使用NumPy内置的功能要好得多,原因如下:NumPy开发团队对它们进行了优化,您需要维护的代码较少,而且您的代码可读性更强.`np.sum`函数在某种意义上是最通用的*和*最有效的,因为它隐藏了实现,并且可能利用了numpy dev对numpy内部的了解.功能很好用. (3认同)
  • 对不起,我不确定你的意思.使用`sum`函数对numpy数组的一个或多个轴进行求和.那是问题吗?你还有别的想法吗? (2认同)

Nic*_*mer 9

对列求和的其他替代方法是

numpy.einsum('ij->j', a)
Run Code Online (Sandbox Code Playgroud)

numpy.dot(a.T, numpy.ones(a.shape[0]))
Run Code Online (Sandbox Code Playgroud)

如果行数和列数处于相同数量级,则所有可能性的速度大致相同:

在此处输入图片说明

但是,如果只有几列,则einsumdot解决方案都显着优于 numpy sum(注意对数刻度):

在此处输入图片说明


重现图的代码:

import numpy
import perfplot


def numpy_sum(a):
    return numpy.sum(a, axis=1)


def einsum(a):
    return numpy.einsum('ij->i', a)


def dot_ones(a):
    return numpy.dot(a, numpy.ones(a.shape[1]))


perfplot.save(
    "out1.png",
    # setup=lambda n: numpy.random.rand(n, n),
    setup=lambda n: numpy.random.rand(n, 3),
    n_range=[2**k for k in range(15)],
    kernels=[numpy_sum, einsum, dot_ones],
    logx=True,
    logy=True,
    xlabel='len(a)',
    )
Run Code Online (Sandbox Code Playgroud)


Ben*_*son 5

使用axis参数:

>> numpy.sum(a, axis=0)
  array([18, 22, 26])
Run Code Online (Sandbox Code Playgroud)