2016-06-16 68 views
1

我试图获得相当于np.unique,但带有'axis = 1'选项。使用numpy获得每行唯一计数〜和〜唯一值

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

我正在寻找每行最高计数值并将其保存为一维矢量。基本上“每行最常见的是哪个值”。

正确答案:[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职位,但它并不完全做我想做的(,要么我不是很聪明到它Munge时间成所需的形式或直接不适用。)

感谢您在提前为您提供任何帮助。

+0

请注意,唯一不能以您想要的方式进行矢量化:每行可能有不同数量的unqiue元素,因此返回将不得不为NumPy中的选项。 – Jaime

回答

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许可条款。 (:我是它的作者声明):

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] 

也就是说,我们首先发现价值的独特计数“一个”配对与它们的行

+0

不错!是的,快得多。这取决于行中可能值的数量。我使用的CIFAR-10仅包含10个可能的值,因此只有10个循环。如果有更多或更多的值存在行,则可能不会扩展。 –

1

一个完全量化的解决方案可以使用numpy_indexed包来实现索引,然后找到由每个行索引形成的组内的这种对的最大数量。

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