使用索引列表列表对numpy矩阵的行进行求和

时间:2017-10-02 21:08:21

标签: python numpy vectorization

使用索引列表和应用函数切片numpy数组,是否可以进行向量化(或非向量化的方式来执行此操作)?矢量化对于大型矩阵来说是理想的

import numpy as np
index = [[1,3], [2,4,5]]
a = np.array(
       [[ 3,  4,  6,  3],
        [ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [1, 1,    4,  5]])

index中的行索引组进行求和,给出:

np.array([[8, 10, 12, 14],
          [17, 19, 24, 37]])

2 个答案:

答案 0 :(得分:4)

方法#1:这是一种几乎*矢量化的方法 -

def sumrowsby_index(a, index):
    index_arr = np.concatenate(index)
    lens = np.array([len(i) for i in index])
    cut_idx = np.concatenate(([0], lens[:-1].cumsum() ))
    return np.add.reduceat(a[index_arr], cut_idx)

*几乎是因为使用循环理解计算lens的步骤,但由于我们只是得到了长度并且没有涉及计算,所以这个步骤不会影响任何大的时间方式。

示例运行 -

In [716]: a
Out[716]: 
array([[ 3,  4,  6,  3],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [ 1,  1,  4,  5]])

In [717]: index
Out[717]: [[1, 3], [2, 4, 5]]

In [718]: sumrowsby_index(a, index)
Out[718]: 
array([[ 8, 10, 12, 14],
       [17, 19, 24, 27]])

方法#2:我们可以利用numpy.dot的快速矩阵乘法来执行这些总和减少,为我们提供另一种方法,如下所示 -

def sumrowsby_index_v2(a, index):
    lens = np.array([len(i) for i in index])
    id_ar = np.zeros((len(lens), a.shape[0]))
    c = np.concatenate(index)
    r = np.repeat(np.arange(len(index)), lens)    
    id_ar[r,c] = 1
    return id_ar.dot(a)

答案 1 :(得分:1)

使用list comprehension ...

对于index list中的每个index,请创建一个新列表,该列表是list rowsa的{​​{1}}。在这里,我们有indexes list numpy我们可以应用arrays方法。在sum() numpy上,array将从添加的sum()返回每个array的新element,这将为您提供所需内容:

arrays

,并提供:

np.array([sum([a[r] for r in i]) for i in index])