如何将给定索引的值分配给数组并在重复索引上取平均值?

时间:2019-09-04 22:06:09

标签: python numpy

是否有一种巧妙的方法可以将值分配给数组中的给定索引,而将平均值分配给重复的索引? 例如:

a = np.array([0, 0, 0, 0, 0])
ind = np.array([1, 1, 2, 3])
b = np.array([2, 3, 4, 5])

并且我想将数组b中的值分配给数组in中以'ind'指示的相应索引,而a [1]应该是2和3的平均值。

我可以尝试一个for循环:

hit = np.zeros_like(a)
for i in range(ind.size):
    hit[ind[i]] += 1
    a[ind[i]] += b[i]
a = a / hit   

但是这段代码看起来很脏。有没有更好的方法来完成这项工作?

4 个答案:

答案 0 :(得分:1)

您可以使用np.where进行此操作。

const Thing => () => {
  const [tagId, setTagId] = useState(null)
  const [query, setQuery] = useState('')

  useEffect(() => {
    if(tagId && tagId !== null) {
       doSomeAjaxAndUpdateResults()
       setQuery('')
    }
  }, [tagId])

  useEffect(() => {
    if(query && query !== '') {
      doSomeAjaxAndUpdateResults()
    }
  }, [query])
}

会导致:

import numpy as np
a = np.array([0, 0, 0, 0, 0]).astype('float64')
ind = np.array([1, 1, 2, 3])
b = np.array([2, 3, 4, 5])

for i in set(ind):
    a[i] = np.mean(b[np.where(ind == i)])

实际上,您正在查找In [5]: a Out[5]: array([0. , 2.5, 4. , 5. , 0. ]) 等于ind的所有ind[index]索引,然后获得i中这些索引的平均值和将该均值分配给b。希望这会有所帮助!

答案 1 :(得分:0)

这是向量化方法。实际的逻辑接近于您自己的解决方案。

n,d = (np.bincount(ind,x,a.size) for x in (b,None))
valid = d!=0
np.copyto(a,np.divide(n,d,where=valid),where=valid)

答案 2 :(得分:0)

In [56]: a = np.zeros(5) 
    ...: hit = np.zeros_like(a) 
    ...: for i in range(ind.size): 
    ...:     hit[ind[i]] += 1 
    ...:     a[ind[i]] += b[i] 

In [57]: a                                                                                                   
Out[57]: array([0., 5., 4., 5., 0.])
In [58]: hit                                                                                                 
Out[58]: array([0., 2., 1., 1., 0.])

提及重复索引使我想到了.at ufunc方法:

In [59]: a = np.zeros(5)                                                                                     
In [60]: a = np.zeros(5) 
    ...: hit = np.zeros_like(a) 
    ...: np.add.at(a,ind,b) 
    ...: np.add.at(hit,ind,1)                                                                                                      
In [61]: a                                                                                                   
Out[61]: array([0., 5., 4., 5., 0.])
In [62]: hit                                                                                                 
Out[62]: array([0., 2., 1., 1., 0.])

这没有a[ind]=b快,但是比循环快。

np.bincount可能会更好地完成此任务,但是add.at值得了解和测试。

https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html

答案 3 :(得分:0)

这不一定是更干净或更快速的方法,但是我认为这是一种易于理解的替代方法:

a = [[] for _ in range(5)]
for i, x in zip(ind, b):
    a[i].append(x)
[np.mean(x) if len(x) else 0 for x in a]