numpy数组-删除重复项

时间:2018-10-28 15:52:57

标签: python-3.x numpy

我正在尝试从numpy数组中删除重复的元素。

Eg:
a = np.array([[0.03,0.32],[0.09,0.26],[0.03,0.32]])
a = np.unique(a,axis=0)

这是完美的工作。 但是问题在于此代码是功能的一部分。我运行该功能说了10次。在任何一次运行中,系统都恰好挂在这条线上。 我注意到数组的最大大小为3500,每个元素(内部数组)的长度为60。 为什么会发生这种情况或任何其他有效的方式?

1 个答案:

答案 0 :(得分:1)

您所做的事情有很多问题。

首先,请注意np.unique不能很好地用于浮点算法,并且通常不会过滤掉“唯一的”浮点数组: < / p>

In [16]: a = np.array([[2.1*3, .123], [6.3, 2.05*.06]])

In [17]: a
Out[17]: 
array([[6.3  , 0.123],
       [6.3  , 0.123]])

In [18]: np.unique(a, axis=0)
Out[18]: 
array([[6.3  , 0.123],
       [6.3  , 0.123]])

请注意,在调用np.unique之后,重复项仍然存在于结果中。其原因是因为np.unique在比较平等的含义时,浮点数必须一点一点地匹配。但是,浮点算法并不精确,因此不能保证您正确过滤掉重复项。

第二,就性能而言,您可以比np.unique做为可散列类型更好。 np.unique将始终在O(n log n)中运行,因为它确实一种。您可以在源代码中对此进行验证:

if optional_indices:
    perm = ar.argsort(kind='mergesort' if return_index else 'quicksort')
    aux = ar[perm]
else:
    ar.sort()
    aux = ar

因此,不管条件的计算方式如何,都对ar(这是输入数组,请参见此处,以获得更多详细信息:https://github.com/numpy/numpy/blob/v1.15.0/numpy/lib/arraysetops.py#L277)执行排序。这样做的原因是因为np.unique支持一组丰富的功能(例如获取dups的索引,返回dups的计数等)。

您不必进行排序即可获得独特的元素。如果将类型击败为可哈希类型(例如tuple),则可以过滤掉线性时间O(n)中的重复项。这是一个示例:

In [37]: b
Out[37]: 
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]

In [39]: np.unique(b, axis=0)
Out[39]: array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

In [40]: set(b)
Out[40]: {(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)}

In [41]: %timeit np.unique(b, axis=0)
21.9 µs ± 132 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [42]: %timeit set(b)
627 ns ± 5.09 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

因此,如您所见,仅使用内置的set的运行速度比np.unique快30倍。请注意,这不适用于浮点数数组,但我只是想说明np.unique从算法的角度来看并不是特别有效。

最后,3500x60并不是那么大。即使使用subpar算法,您也可以很轻松地遍历该循环,并且它不应挂在任何现代硬件上。它应该运行得很快:

In [43]: np.random.seed(0)

In [46]: x = np.random.random((3500, 60))

In [49]: %timeit np.unique(x, axis=0)
2.57 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

因此,在我的MacBook Pro上花费的时间为2.57毫秒,这在硬件(2.3 GHz i5、8GB RAM)方面并不是一个强大的工具。 确保您正在对代码进行概要分析,并确保此问题中的行实际上是 麻烦行。

HTH。