Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 删除NumPy数组中具有重复项的行_Python_Performance_Numpy_Vectorization - Fatal编程技术网

Python 删除NumPy数组中具有重复项的行

Python 删除NumPy数组中具有重复项的行,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,我有一个(N,3)numpy值数组: >>> vals = numpy.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]]) >>> vals array([[1, 2, 3], [4, 5, 6], [7, 8, 7], [0, 4, 5], [2, 2, 1], [0, 0, 0], [5, 4,

我有一个
(N,3)
numpy值数组:

>>> vals = numpy.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]])
>>> vals
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 7],
       [0, 4, 5],
       [2, 2, 1],
       [0, 0, 0],
       [5, 4, 3]])
我想从数组中删除具有重复值的行。例如,上述数组的结果应为:

>>> duplicates_removed
array([[1, 2, 3],
       [4, 5, 6],
       [0, 4, 5],
       [5, 4, 3]])
我不知道如何在不循环的情况下有效地使用numpy(数组可能相当大)。有人知道我怎么做吗

numpy.array([v for v in vals if len(set(v)) == len(v)])
请注意,这仍然是幕后的循环。你无法避免。但它应该可以很好地工作,即使是数百万行

请注意,这仍然是幕后的循环。你无法避免。但即使对于数百万行,它也应该可以正常工作。

这是一个选项:

import numpy
vals = numpy.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]])
a = (vals[:,0] == vals[:,1]) | (vals[:,1] == vals[:,2]) | (vals[:,0] == vals[:,2])
vals = numpy.delete(vals, numpy.where(a), axis=0)
这是一个选项:

import numpy
vals = numpy.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]])
a = (vals[:,0] == vals[:,1]) | (vals[:,1] == vals[:,2]) | (vals[:,0] == vals[:,2])
vals = numpy.delete(vals, numpy.where(a), axis=0)

与Marcelo相同,但我认为使用
numpy.unique()
而不是
set()
可能会完全理解您的拍摄目的

numpy.array([v for v in vals if len(numpy.unique(v)) == len(v)])

与Marcelo相同,但我认为使用
numpy.unique()
而不是
set()
可能会完全理解您的拍摄目的

numpy.array([v for v in vals if len(numpy.unique(v)) == len(v)])

这里有一种处理通用列数的方法,它仍然是一种矢量化方法-

def rows_uniq_elems(a):
    a_sorted = np.sort(a,axis=-1)
    return a[(a_sorted[...,1:] != a_sorted[...,:-1]).all(-1)]
步骤:

  • 按每行排序

  • 查找每行中连续元素之间的差异。因此,任何至少有一个零微分的行都表示重复的元素。我们将使用它来获得有效行的掩码。因此,最后一步是使用掩码从输入数组中简单地选择有效行

样本运行-

In [49]: a
Out[49]: 
array([[1, 2, 3, 7],
       [4, 5, 6, 7],
       [7, 8, 7, 8],
       [0, 4, 5, 6],
       [2, 2, 1, 1],
       [0, 0, 0, 3],
       [5, 4, 3, 2]])

In [50]: rows_uniq_elems(a)
Out[50]: 
array([[1, 2, 3, 7],
       [4, 5, 6, 7],
       [0, 4, 5, 6],
       [5, 4, 3, 2]])

这里有一种处理通用列数的方法,它仍然是一种矢量化方法-

def rows_uniq_elems(a):
    a_sorted = np.sort(a,axis=-1)
    return a[(a_sorted[...,1:] != a_sorted[...,:-1]).all(-1)]
步骤:

  • 按每行排序

  • 查找每行中连续元素之间的差异。因此,任何至少有一个零微分的行都表示重复的元素。我们将使用它来获得有效行的掩码。因此,最后一步是使用掩码从输入数组中简单地选择有效行

样本运行-

In [49]: a
Out[49]: 
array([[1, 2, 3, 7],
       [4, 5, 6, 7],
       [7, 8, 7, 8],
       [0, 4, 5, 6],
       [2, 2, 1, 1],
       [0, 0, 0, 3],
       [5, 4, 3, 2]])

In [50]: rows_uniq_elems(a)
Out[50]: 
array([[1, 2, 3, 7],
       [4, 5, 6, 7],
       [0, 4, 5, 6],
       [5, 4, 3, 2]])

六年过去了,但这个问题对我很有帮助,所以我对Divakar、Benjamin、Marcelo Cantos和Curtis Patrick给出的答案进行了速度比较

import numpy as np
vals = np.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]])

def rows_uniq_elems1(a):
    idx = a.argsort(1)
    a_sorted = a[np.arange(idx.shape[0])[:,None], idx]
    return a[(a_sorted[:,1:] != a_sorted[:,:-1]).all(-1)]

def rows_uniq_elems2(a):
    a = (a[:,0] == a[:,1]) | (a[:,1] == a[:,2]) | (a[:,0] == a[:,2])
    return np.delete(a, np.where(a), axis=0)

def rows_uniq_elems3(a):
    return np.array([v for v in a if len(set(v)) == len(v)])

def rows_uniq_elems4(a):
    return np.array([v for v in a if len(np.unique(v)) == len(v)])
结果:

%timeit rows_uniq_elems1(vals)
10000 loops, best of 3: 67.9 µs per loop

%timeit rows_uniq_elems2(vals)
10000 loops, best of 3: 156 µs per loop

%timeit rows_uniq_elems3(vals)
1000 loops, best of 3: 59.5 µs per loop

%timeit rows_uniq_elems(vals)
10000 loops, best of 3: 268 µs per loop
似乎使用
set
胜过
numpy.unique
。在我的例子中,我需要在更大的阵列上执行此操作:

bigvals = np.random.randint(0,10,3000).reshape([3,1000])

%timeit rows_uniq_elems1(bigvals)
10000 loops, best of 3: 276 µs per loop

%timeit rows_uniq_elems2(bigvals)
10000 loops, best of 3: 192 µs per loop

%timeit rows_uniq_elems3(bigvals)
10000 loops, best of 3: 6.5 ms per loop

%timeit rows_uniq_elems4(bigvals)
10000 loops, best of 3: 35.7 ms per loop
没有列表理解的方法要快得多。然而,行的数量是硬编码的,并且很难扩展到三列以上,因此在我的例子中,至少对集合的列表理解是最好的答案


编辑了,因为六年过去了,我混淆了
bigvals

中的行和列,但这个问题帮助了我,所以我对Divakar、Benjamin、Marcelo Cantos和Curtis Patrick给出的答案进行了速度比较

import numpy as np
vals = np.array([[1,2,3],[4,5,6],[7,8,7],[0,4,5],[2,2,1],[0,0,0],[5,4,3]])

def rows_uniq_elems1(a):
    idx = a.argsort(1)
    a_sorted = a[np.arange(idx.shape[0])[:,None], idx]
    return a[(a_sorted[:,1:] != a_sorted[:,:-1]).all(-1)]

def rows_uniq_elems2(a):
    a = (a[:,0] == a[:,1]) | (a[:,1] == a[:,2]) | (a[:,0] == a[:,2])
    return np.delete(a, np.where(a), axis=0)

def rows_uniq_elems3(a):
    return np.array([v for v in a if len(set(v)) == len(v)])

def rows_uniq_elems4(a):
    return np.array([v for v in a if len(np.unique(v)) == len(v)])
结果:

%timeit rows_uniq_elems1(vals)
10000 loops, best of 3: 67.9 µs per loop

%timeit rows_uniq_elems2(vals)
10000 loops, best of 3: 156 µs per loop

%timeit rows_uniq_elems3(vals)
1000 loops, best of 3: 59.5 µs per loop

%timeit rows_uniq_elems(vals)
10000 loops, best of 3: 268 µs per loop
似乎使用
set
胜过
numpy.unique
。在我的例子中,我需要在更大的阵列上执行此操作:

bigvals = np.random.randint(0,10,3000).reshape([3,1000])

%timeit rows_uniq_elems1(bigvals)
10000 loops, best of 3: 276 µs per loop

%timeit rows_uniq_elems2(bigvals)
10000 loops, best of 3: 192 µs per loop

%timeit rows_uniq_elems3(bigvals)
10000 loops, best of 3: 6.5 ms per loop

%timeit rows_uniq_elems4(bigvals)
10000 loops, best of 3: 35.7 ms per loop
没有列表理解的方法要快得多。然而,行的数量是硬编码的,并且很难扩展到三列以上,因此在我的例子中,至少对集合的列表理解是最好的答案



编辑了,因为我混淆了
bigvals中的行和列

我提出了
[VAL中的项对项如果计数器(项)。最常见的(1)[0][1]是1]
,但这更好,特别是因为你已经知道
len(v)
。然而,你仍然在“循环”,因为你正在迭代数组。尽管我需要重复项的索引位置,但这对于一个大数组来说速度惊人,所以我喜欢@Benjamin的解决方案,我想出了
[VAL if计数器中的项对项(项)。最常见的(1)[0][1]是1]
,但这更好,特别是因为你已经知道了len(v)。但是,你仍然在“循环”,因为你在数组上迭代。尽管我需要重复项的索引位置,但对于一个大数组来说,这实际上是惊人的快,所以我喜欢@Benjamin的solutionBy“无循环”你是什么意思?你必须检查数组中的每一项,所以不管你使用什么技巧来隐藏循环,它都是O(m*n)。我认为他的意思是在Numpy中循环,而不是在Python中循环。编译后的Numpy函数中的O(mn)比Python
for
循环中的O(mn)快得多。当选项是编译代码和解释代码时,常量很重要。因为,您希望将其推广到处理通用列数,所以您可能会发现这个问题值得一读。您所说的“无循环”是什么意思?你必须检查数组中的每一项,所以不管你使用什么技巧来隐藏循环,它都是O(m*n)。我认为他的意思是在Numpy中循环,而不是在Python中循环。编译后的Numpy函数中的O(mn)比Python
for
循环中的O(mn)快得多。当选项是编译代码和解释代码时,常量很重要。因为,您希望将其推广到处理通用列数,所以您可能会发现这个问题值得一读。好吧,
set
也有同样的意图,但它是
numpy.unique
更快,也许?它实际上似乎要慢得多-对于numpy.unique()来说是23秒,而对于set()来说是3秒。在我的机器上,有100万rowsWell,
set
也达到了同样的目的,但它是
numpy.unique
更快,也许?它实际上似乎要慢得多-对于numpy.unique()来说是23秒,对于set()来说是3秒在我的机器上,有一百万罗西,我正在努力解决这个问题,干得好。但是你不需要| not^吗?这比列表理解方法快得多,所以我可能会接受。想知道是否有任何方法可以推广到NxM吗?@Ned Batchelder:是的,尽管在这种情况下它不会改变任何东西。@jterrace你可以通过生成0-m的组合进行推广,在生成器表达式中使用它们进行比较,然后减少
|
得到
a
。我正试图解决这个问题,干得好日分