基于另一个数组中的值,为每个匹配元素在第三个数组中汇总一个数组的值

9
我有两个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)]))

生成的 catsums 应该是:
[1, 14, 7, 8, 12, 13]

我当前的运行时间大约为5微秒。我对Python还比较新,希望能够通过将前两个数组合并或使用lambda等更快的解决方案。

谢谢阅读!


1
根据您提供的示例,您期望的输出是什么? - piRSquared
添加到文本中,感谢指出这个疏漏! - hrschbck
1
您的问题已被点赞,您现在有15个声望值,可以随意点赞并接受@piRSquared的答案。 - BENY
2个回答

9
你可以使用 searchsortedbincount -
np.bincount(np.searchsorted(categories, valcats), values)

如果类别数组尚未排序,您会添加什么? - piRSquared
@piRSquared 我会先对其进行排序,然后将其输入解决方案。 - Divakar
我想的更多是通过传递sorter参数...,sorter = categories.argsort() - piRSquared
1
@piRSquared 这会涉及到很多开销。我认为对于这样的情况不值得。 - Divakar
@hrschbck 如果你想要一个简单的方法,可以这样做:ids = np.searchsorted(categories, valcats) 然后 df.groupby('ids')['values'].max().values。如果你想要求和,可以重复使用 idsnp.bincount(ids, values) - Divakar

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 将占据主导地位。


4
好的解决方案~ +1 - BENY
谢谢@Wen (-: - piRSquared
非常感谢您的解释! - BENY
那是一个新问题...我有一个答案给你。 - piRSquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接