使用numpy获得每行的唯一count~和〜唯一值

时间:2016-06-16 01:32:28

标签: python numpy

我试图获得相当于np.unique,但是使用'axis = 1'选项。

a = np.array([[8, 8, 8, 5, 8],
       [8, 2, 0, 8, 8],
       [4, 5, 4, 2, 4],
       [4, 6, 5, 2, 6]])

我希望获得每行中具有最高计数的值并将其保存为1D向量。基本上“每行中最常见的是哪个值。”

正确答案:本例中[8,8,4,6]。

现在我正在做类似的事情:

y = np.zeros(len(a))

for i in xrange(len(a)):
    [u,cnt] = np.unique(a[i,:],return_counts=True)
    # pick the value from 'u' that is seen the most.
    y[i] = u[np.argmax(cnt)]

它提供了所需的结果,但在循环遍历数千行时,Python非常慢。我正在寻找一种完全矢量化的方法。

我发现了unique row elements帖子,但它并没有完全符合我的要求(而且要么我不够聪明,不能将其固化成所需的形式,或者它不能直接适用。)

提前感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:1)

一种选择是使用scipy.stats.mode

In [36]: from scipy.stats import mode

In [37]: a
Out[37]: 
array([[8, 8, 8, 5, 8],
       [8, 2, 0, 8, 8],
       [4, 5, 4, 2, 4],
       [4, 6, 5, 2, 6]])

In [38]: vals, counts = mode(a, axis=1)

In [39]: vals
Out[39]: 
array([[8],
       [8],
       [4],
       [6]])

In [40]: counts
Out[40]: 
array([[4],
       [3],
       [3],
       [2]])

但是,它是使用numpy在Python中编写的,并且根据输入中值的分布,它可能不会比您的解决方案更快。您可以在https://github.com/scipy/scipy/blob/master/scipy/stats/stats.py中找到实现(当我写这篇文章时,它就在这里:https://github.com/scipy/scipy/blob/master/scipy/stats/stats.py#L372)。

该函数的基本部分仅取决于numpy,因此如果它对您有效,但您不希望依赖于scipy,则可以将该函数复制到您自己的项目中 - 只需确保遵循scipy使用的BSD许可条款。

答案 1 :(得分:1)

可以使用numpy_indexed包实现完全向量化的解决方案(免责声明:我是其作者):

import numpy_indexed as npi
r = np.indices(a.shape)[0]
(ua, ur), c = npi.unique((a.flatten(), r.flatten()), return_count=True)
u, i = npi.group_by(ur).argmax(c)
y = ua[i]

也就是说,我们首先找到'a'中与行索引配对的值的唯一计数,然后在每个行索引形成的组中找到此类对的最大计数。

在'a'中仅使用10个可能的值我不确定这比当前接受的答案更快,但这种方法的时间复杂度不是'a'中使用的位数的函数,所以它应该更好地扩展到具有更多标签的数据集。