根据数组的值求和

发布于 2021-01-29 14:10:25

我有未排序的索引数组:

i = np.array([1,5,2,6,4,3,6,7,4,3,2])

我也有一个相同长度的值数组:

v = np.array([2,5,2,3,4,1,2,1,6,4,2])

我有期望值为零的数组:

d = np.zeros(10)

现在,我想根据v在d中的索引将其添加到元素中。

如果我用普通的python做,我会这样:

for index,value in enumerate(v):
    idx = i[index]
    d[idx] += v[index]

这是丑陋且效率低下的。我该如何更改?

关注者
0
被浏览
113
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我们可以使用np.bincount据称对这种累积加权计数非常有效的方法,所以这里有一个-

    counts = np.bincount(i,v)
    d[:counts.size] = counts
    

    或者,使用minlength输入参数,对于一般情况,当d可以是任何数组,而我们想添加到该数组中时,

    d += np.bincount(i,v,minlength=d.size).astype(d.dtype, copy=False)
    

    运行时测试

    本节将本文中np.add.at列出的基础方法other post与本文np.bincount前面列出的基础方法进行比较。

    In [61]: def bincount_based(d,i,v):
        ...:     counts = np.bincount(i,v)
        ...:     d[:counts.size] = counts
        ...: 
        ...: def add_at_based(d,i,v):
        ...:     np.add.at(d, i, v)
        ...:
    
    In [62]: # Inputs (random numbers)
        ...: N = 10000
        ...: i = np.random.randint(0,1000,(N))
        ...: v = np.random.randint(0,1000,(N))
        ...: 
        ...: # Setup output arrays for two approaches
        ...: M = 12000
        ...: d1 = np.zeros(M)
        ...: d2 = np.zeros(M)
        ...:
    
    In [63]: bincount_based(d1,i,v) # Run approaches
        ...: add_at_based(d2,i,v)
        ...:
    
    In [64]: np.allclose(d1,d2)  # Verify outputs
    Out[64]: True
    
    In [67]: # Setup output arrays for two approaches again for timing
        ...: M = 12000
        ...: d1 = np.zeros(M)
        ...: d2 = np.zeros(M)
        ...:
    
    In [68]: %timeit add_at_based(d2,i,v)
    1000 loops, best of 3: 1.83 ms per loop
    
    In [69]: %timeit bincount_based(d1,i,v)
    10000 loops, best of 3: 52.7 µs per loop
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看