2d NumPy数组中每个元素的计数

2024-10-06 12:25:54 发布

您现在位置:Python中文网/ 问答频道 /正文

假设您有一个2D数组(作为NumPyint数组),如下所示:

[[2,2,3,3],
 [2,3,3,3],
 [3,3,4,4]]

现在,您希望得到一个形状相同的数组,但不是原始值,而是用其出现的次数替换该数字。也就是说,数字2变为3,因为发生了3次,3s变成7s,4s变成2s

所以输出结果是:

^{pr2}$

我的解决方案是首先创建一个字典,它将所有原始值保存为键,并将出现的次数作为值。20000x2000的数组看起来很慢。在

我如何才能更有效地实现这一目标?在

谢谢!在


Tags: 目标字典数字数组解决方案次数形状pr2
3条回答

一种方法是使用numpy.unique来提取值计数。在

然后转换为字典并使用numpy.vectorize来使用这个字典映射。在

import numpy as np

A = np.array([[2,2,3,3],
              [2,3,3,3],
              [3,3,4,4]])

d = dict(zip(*np.unique(A.ravel(), return_counts=True)))

res = np.vectorize(d.get)(A)

array([[3, 3, 7, 7],
       [3, 7, 7, 7],
       [7, 7, 2, 2]], dtype=int64)

性能

我看到上面的方法对于2000x2000数组需要~2s,而通过基于字典的方法是3s。但是PaulPanzer和{a2}的纯numpy溶液仍然更快。在

^{pr2}$

我相信您应该可以在这里通过使用return_inversenp.unique()内使用return_inverse

If True, also return the indices of the unique array (for the specified axis, if provided) that can be used to reconstruct ar.

>>> import numpy as np

>>> a = np.array([[2,2,3,3],
...               [2,3,3,3],
...               [3,3,4,4]])

>>> _, inv, cts = np.unique(a, return_inverse=True, return_counts=True)
>>> cts[inv].reshape(a.shape)

array([[3, 3, 7, 7],
       [3, 7, 7, 7],
       [7, 7, 2, 2]])

这也适用于扁平数组未排序的情况,例如b = np.array([[1, 2, 4], [4, 4, 1]])。在

以下是一种利用值为int的方法:

MAX_LOOKUP = 2**24

def f_pp(a):
    mn, mx = a.min(), a.max()
    span = mx-mn+1
    if span > MAX_LOOKUP:
        raise RuntimeError('values spread to wide')
    a = a - mn
    return np.bincount(a.ravel(), None, span)[a]

时间安排(主要基于@jpp的工作):

^{pr2}$

相关问题 更多 >