给定索引列表的数组的部分和

时间:2020-11-30 21:32:28

I have a 2D matrix and I need to sum a subset of the matrix elements, given two lists of indices imp_list and bath_list. Here is what I'm doing right now:

我有一个二维矩阵,我需要对矩阵元素的子集求和,给定两个索引imp_list和bath_list。以下是我现在正在做的:

s = 0.0
for i in imp_list:
    for j in bath_list:
        s += K[i,j]

which appears to be very slow. What would be a better solution to perform the sum?

看起来很慢。什么是更好的解来执行求和?

1 个解决方案

#1


4  

If you're working with large arrays, you should get a huge speed boost by using NumPy's own indexing routines over Python's for loops.

如果您使用的是大型数组,那么通过使用NumPy自己的索引例程而不是Python的for循环,您将获得巨大的速度提升。

In the general case you can use np.ix_ to select a subarray of the matrix to sum:

一般情况下你可以用np。选择矩阵的一个子数组求和:

K[np.ix_(imp_list, bath_list)].sum()

Note that np.ix_ carries some overhead, so if your two lists contain consecutive or evenly-spaced values, it's worth using regular slicing to index the array instead (see method3() below).

注意,np。ix_会带来一些开销,所以如果您的两个列表包含连续的或均匀间隔的值,那么使用常规的分段来索引数组是值得的(参见下面的method3()))。

Here's some data to illustrate the improvements:

以下是一些数据来说明这些改进:

K = np.arange(1000000).reshape(1000, 1000)
imp_list = range(100)  # [0, 1, 2, ..., 99]
bath_list = range(200) # [0, 1, 2, ..., 199]

def method1():
    s = 0
    for i in imp_list:
        for j in bath_list:
            s += K[i,j]
    return s

def method2():
    return K[np.ix_(imp_list, bath_list)].sum()

def method3():
    return K[:100, :200].sum()

Then:

然后:

In [80]: method1() == method2() == method3()
Out[80]: True

In [91]: %timeit method1()
10 loops, best of 3: 9.93 ms per loop

In [92]: %timeit method2()
1000 loops, best of 3: 884 µs per loop

In [93]: %timeit method3()
10000 loops, best of 3: 34 µs per loop

#1


4  

If you're working with large arrays, you should get a huge speed boost by using NumPy's own indexing routines over Python's for loops.

如果您使用的是大型数组,那么通过使用NumPy自己的索引例程而不是Python的for循环,您将获得巨大的速度提升。

In the general case you can use np.ix_ to select a subarray of the matrix to sum:

一般情况下你可以用np。选择矩阵的一个子数组求和:

K[np.ix_(imp_list, bath_list)].sum()

Note that np.ix_ carries some overhead, so if your two lists contain consecutive or evenly-spaced values, it's worth using regular slicing to index the array instead (see method3() below).

注意,np。ix_会带来一些开销,所以如果您的两个列表包含连续的或均匀间隔的值,那么使用常规的分段来索引数组是值得的(参见下面的method3()))。

Here's some data to illustrate the improvements:

以下是一些数据来说明这些改进:

K = np.arange(1000000).reshape(1000, 1000)
imp_list = range(100)  # [0, 1, 2, ..., 99]
bath_list = range(200) # [0, 1, 2, ..., 199]

def method1():
    s = 0
    for i in imp_list:
        for j in bath_list:
            s += K[i,j]
    return s

def method2():
    return K[np.ix_(imp_list, bath_list)].sum()

def method3():
    return K[:100, :200].sum()

Then:

然后:

In [80]: method1() == method2() == method3()
Out[80]: True

In [91]: %timeit method1()
10 loops, best of 3: 9.93 ms per loop

In [92]: %timeit method2()
1000 loops, best of 3: 884 µs per loop

In [93]: %timeit method3()
10000 loops, best of 3: 34 µs per loop