NumPy根据第三个数组中每个匹配元素的另一个数组中的值对一个数组求和

时间:2017-07-23 16:24:59

标签: python arrays pandas numpy

我有两个numpy数组,一个包含值,另一个包含每个值类别。

values=np.array([1,2,3,4,5,6,7,8,9,10])
valcats=np.array([101,301,201,201,102,302,302,202,102,301])

我有另一个数组,其中包含我想要总结的唯一类别。

categories=np.array([101,102,201,202,301,302])

我的问题是,我将运行相同的求和过程几十亿次,每微秒都很重要。

我目前的实施情况如下。

catsums=[]
for x in categories:
    catsums.append(np.sum(values[np.where(valcats==x)]))

产生的catums应该是:

[1, 14, 7, 8, 12, 13]

我当前的运行时间约为5μs。我对Python有些新意,希望通过潜在地结合前两个数组或lamdba或者我甚至不知道的很酷的东西找到一个快速的解决方案。

感谢阅读!

2 个答案:

答案 0 :(得分:8)

@Divakar刚刚发布了一个非常好的答案。如果您已经定义了类别数组,我会使用@Divakar的答案。如果您没有定义唯一值,我会使用我的。

我会使用pd.factorize对类别进行分解。然后使用np.bincount并将weights参数设置为values数组

f, u = pd.factorize(valcats)
np.bincount(f, values).astype(values.dtype)

array([ 1, 12,  7, 14, 13,  8])

pd.factorize也会在u变量中生成唯一值。我们可以使用u排列结果,看看我们是否已找到正确的解决方案。

np.column_stack([u, np.bincount(f, values).astype(values.dtype)])

array([[101,   1],
       [301,  12],
       [201,   7],
       [102,  14],
       [302,  13],
       [202,   8]])

使用pd.Series

可以使这一点更加明显
f, u = pd.factorize(valcats)
pd.Series(np.bincount(f, values).astype(values.dtype), u)

101     1
301    12
201     7
102    14
302    13
202     8
dtype: int64

为什么 pd.factorize 而不是 np.unique

我们可以用

等效地做到这一点
 u, f = np.unique(valcats, return_inverse=True)

但是,np.unique对值进行排序,并在nlogn时间内运行。另一方面,pd.factorize不会在线性时间内排序和运行。对于较大的数据集,pd.factorize将主导性能。

答案 1 :(得分:8)

您可以使用searchsortedbincount -

np.bincount(np.searchsorted(categories, valcats), values)