在numpy中按数字求和数组

Scr*_*ter 17 python numpy

假设我有一个numpy数组,如:[1,2,3,4,5,6]和另一个数组:[0,0,1,2,2,1]我想按组对第一个数组中的项求和(第二个数组)并获得n组结果的组号顺序(在这种情况下,结果将是[3,9,9]).我怎么做numpy?

Ale*_*lex 29

numpy函数bincount完全是为了这个目的而制作的,我相信它会比其他方法对所有大小的输入快得多:

data = [1,2,3,4,5,6]
ids  = [0,0,1,2,2,1]

np.bincount(ids, weights=data) #returns [3,9,9] as a float64 array
Run Code Online (Sandbox Code Playgroud)

输出的第i个元素是data对应于"id" 的所有元素的总和i.

希望有所帮助.

  • 很棒的方法。请注意,bincount 需要 `int` id。 (2认同)

Bi *_*ico 27

这是一种基于numpy.unique的实现来实现此总和的矢量化方法.根据我的时间,它比循环方法快500倍,比直方图方法快100倍.

def sum_by_group(values, groups):
    order = np.argsort(groups)
    groups = groups[order]
    values = values[order]
    values.cumsum(out=values)
    index = np.ones(len(groups), 'bool')
    index[:-1] = groups[1:] != groups[:-1]
    values = values[index]
    groups = groups[index]
    values[1:] = values[1:] - values[:-1]
    return values, groups
Run Code Online (Sandbox Code Playgroud)


Joe*_*ton 9

有多种方法可以做到这一点,但这是一种方式:

import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])

unique_groups = np.unique(groups)
sums = []
for group in unique_groups:
    sums.append(data[groups == group].sum())
Run Code Online (Sandbox Code Playgroud)

可以对事物进行矢量化,以便根本没有for循环,但我建议不要这样做.它变得不可读,并且需要一些2D临时阵列,如果你有大量数据,可能需要大量内存.

编辑:这是你可以完全矢量化的一种方式.请记住,这可能(并且可能会)比上面的版本慢.(并且可能有一种更好的方法来对此进行矢量化,但现在已经很晚了,我已经累了,所以这只是第一件让我感到震惊的事情......)

但是,请记住,这是一个不好的例子...你在上面的循环中真的会更好(在速度和可读性方面)...

import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])

unique_groups = np.unique(groups)

# Forgive the bad naming here...
# I can't think of more descriptive variable names at the moment...
x, y = np.meshgrid(groups, unique_groups)
data_stack = np.tile(data, (unique_groups.size, 1))

data_in_group = np.zeros_like(data_stack)
data_in_group[x==y] = data_stack[x==y]

sums = data_in_group.sum(axis=1)
Run Code Online (Sandbox Code Playgroud)


Sve*_*ach 7

如果组由连续的整数索引,则可以滥用该numpy.histogram()函数来获得结果:

data = numpy.arange(1, 7)
groups = numpy.array([0,0,1,2,2,1])
sums = numpy.histogram(groups, 
                       bins=numpy.arange(groups.min(), groups.max()+2), 
                       weights=data)[0]
# array([3, 9, 9])
Run Code Online (Sandbox Code Playgroud)

这将避免任何Python循环.


cai*_*ura 5

我尝试过每个人的脚本,我的考虑是:

乔:只有少数几个小组才能工作.

kevpie:由于循环太慢(这不是pythonic方式)

Bi_Rico和Sven:表现不错,但只适用于Int32(如果总和超过2 ^ 32/2则会失败)

亚历克斯:是最快的一个,总和很好.

但是,如果您想要更灵活,并且可以通过其他统计数据进行分组,请使用SciPy:

from scipy import ndimage

data = np.arange(10000000)
groups = np.arange(1000).repeat(10000)
ndimage.sum(data, groups, range(1000))
Run Code Online (Sandbox Code Playgroud)

这很好,因为你有很多分组统计(总和,均值,方差,......).


Pet*_*ter 5

你们都错了!最好的方法是:

a = [1,2,3,4,5,6]
ix = [0,0,1,2,2,1]
accum = np.zeros(np.max(ix)+1)
np.add.at(accum, ix, a)
print accum
> array([ 3.,  9.,  9.])
Run Code Online (Sandbox Code Playgroud)