首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最快的方法来计数相同的子数组在一个和数组?

最快的方法来计数相同的子数组在一个和数组?
EN

Stack Overflow用户
提问于 2014-10-15 14:10:55
回答 3查看 450关注 0票数 2

让我们考虑一个2d数组A。

代码语言:javascript
复制
2   3   5   7
2   3   5   7
1   7   1   4
5   8   6   0
2   3   5   7

第一行、第二行和最后一行是相同的。我正在寻找的算法应该返回每个不同行的相同行数(=每个元素的重复数)。如果可以轻松地修改脚本,以便也计算相同列的数量,那就太好了。

我使用了一种效率低下的天真算法来做到这一点:

代码语言:javascript
复制
import numpy
A=numpy.array([[2,  3,  5,  7],[2,  3,  5,  7],[1,  7,  1,  4],[5,  8,  6,  0],[2,  3,  5,  7]])
i=0
end = len(A)
while i<end:
    print i,
    j=i+1
    numberID = 1
    while j<end:
        print j
        if numpy.array_equal(A[i,:] ,A[j,:]):
            numberID+=1
        j+=1
    i+=1
print A, len(A)

预期结果:

代码语言:javascript
复制
array([3,1,1]) # number identical arrays per line

我的algo看起来就像在numpy中使用原生python,因此效率低下。谢谢你帮忙。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-15 20:48:10

在unumpy >= 1.9.0中,np.unique有一个return_counts关键字参数,您可以结合解决方案这里来获取计数:

代码语言:javascript
复制
b = np.ascontiguousarray(A).view(np.dtype((np.void, A.dtype.itemsize * A.shape[1])))
unq_a, unq_cnt = np.unique(b, return_counts=True)
unq_a = unq_a.view(A.dtype).reshape(-1, A.shape[1])

>>> unq_a
array([[1, 7, 1, 4],
       [2, 3, 5, 7],
       [5, 8, 6, 0]])

>>> unq_cnt
array([1, 3, 1])

在较老的numpy中,您可以复制np.unique 有吗?,它看起来类似于:

代码语言:javascript
复制
a_view = np.array(A, copy=True)
a_view = a_view.view(np.dtype((np.void,
                               a_view.dtype.itemsize*a_view.shape[1]))).ravel()
a_view.sort()
a_flag = np.concatenate(([True], a_view[1:] != a_view[:-1]))
a_unq = A[a_flag]
a_idx = np.concatenate(np.nonzero(a_flag) + ([a_view.size],))
a_cnt = np.diff(a_idx)

>>> a_unq
array([[1, 7, 1, 4],
       [2, 3, 5, 7],
       [5, 8, 6, 0]])

>>> a_cnt
array([1, 3, 1])
票数 3
EN

Stack Overflow用户

发布于 2014-10-15 16:37:00

您可以对行项进行词汇排序,这将为您提供按排序顺序遍历行的索引,使搜索结果为O(n)而不是O(n^2)。注意,默认情况下,最后一列中的元素最后排序,即行从右到左,而不是从左到右。

代码语言:javascript
复制
In [9]: a
Out[9]: 
array([[2, 3, 5, 7],
       [2, 3, 5, 7],
       [1, 7, 1, 4],
       [5, 8, 6, 0],
       [2, 3, 5, 7]])

In [10]: lexsort(a.T)
Out[10]: array([3, 2, 0, 1, 4])

In [11]: a[lexsort(a.T)]
Out[11]: 
array([[5, 8, 6, 0],
       [1, 7, 1, 4],
       [2, 3, 5, 7],
       [2, 3, 5, 7],
       [2, 3, 5, 7]])
票数 2
EN

Stack Overflow用户

发布于 2014-10-15 14:30:18

为此,您可以从Counter模块中使用collections类。

它的工作方式如下:

代码语言:javascript
复制
x = [2, 2, 1, 5, 2]
from collections import Counter
c=Counter(x)
print c

输出:计数器({2: 3,1: 1,5: 1})

您将面临的唯一问题是在您的情况下,因为x的每个值本身都是一个列表,这是一个不可接受的数据结构。如果您可以在元组中转换x的每个值,那么它应该以如下方式工作:

代码语言:javascript
复制
x = [(2,  3,  5,  7),(2,  3,  5,  7),(1,  7,  1,  4),(5,  8,  6,  0),(2,  3,  5,  7)]
from collections import Counter
c=Counter(x)
print c

输出:计数器({(2,3,5,7):3,(5,8,6,0):1,(1,7,1,4):1})

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26384719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档