我需要在numpy.array中找到唯一的行。
例如:
>>> a # I have
array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
>>> new_a # I want to get to
array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 0]])
我知道我可以创建一个集和循环数组,但我正在寻找一个有效的纯numpy解决方案。我相信有一种方法可以将数据类型设置为void,然后我可以使用numpy。唯一的,但我不知道如何让它工作。
np。Unique的工作原理是对一个扁平数组排序,然后查看每一项是否等于前一项。这可以手动完成,无需压平:
ind = np.lexsort(a.T)
a[ind[np.concatenate(([True],np.any(a[ind[1:]]!=a[ind[:-1]],axis=1)))]]
这个方法不使用元组,应该比这里给出的其他方法更快更简单。
注意:以前的版本在A[后面没有ind,这意味着使用了错误的索引。另外,Joe Kington提出了一个很好的观点,这确实产生了各种各样的中间副本。下面的方法通过创建一个排序副本,然后使用它的视图来生成更少的副本:
b = a[np.lexsort(a.T)]
b[np.concatenate(([True], np.any(b[1:] != b[:-1],axis=1)))]
这样更快,使用的内存更少。
同样,如果你想在ndarray中找到唯一的行,而不管数组中有多少个维度,下面的方法可以工作:
b = a[lexsort(a.reshape((a.shape[0],-1)).T)];
b[np.concatenate(([True], np.any(b[1:]!=b[:-1],axis=tuple(range(1,a.ndim)))))]
剩下的一个有趣的问题是,如果你想沿着任意维度数组的任意轴进行排序/惟一,这将更加困难。
编辑:
为了演示速度差异,我在ipython中对答案中描述的三种不同方法进行了一些测试。使用你的精确的a,没有太大的区别,尽管这个版本稍微快一点:
In [87]: %timeit unique(a.view(dtype)).view('<i8')
10000 loops, best of 3: 48.4 us per loop
In [88]: %timeit ind = np.lexsort(a.T); a[np.concatenate(([True], np.any(a[ind[1:]]!= a[ind[:-1]], axis=1)))]
10000 loops, best of 3: 37.6 us per loop
In [89]: %timeit b = [tuple(row) for row in a]; np.unique(b)
10000 loops, best of 3: 41.6 us per loop
然而,使用更大的a,这个版本最终会快得多:
In [96]: a = np.random.randint(0,2,size=(10000,6))
In [97]: %timeit unique(a.view(dtype)).view('<i8')
10 loops, best of 3: 24.4 ms per loop
In [98]: %timeit b = [tuple(row) for row in a]; np.unique(b)
10 loops, best of 3: 28.2 ms per loop
In [99]: %timeit ind = np.lexsort(a.T); a[np.concatenate(([True],np.any(a[ind[1:]]!= a[ind[:-1]],axis=1)))]
100 loops, best of 3: 3.25 ms per loop
最直接的解决方案是通过使行成为字符串,使行成为单个项。然后可以使用numpy将每一行作为一个整体进行比较,以确定其唯一性。这个解决方案是可推广的,你只需要重塑和转置你的数组为其他组合。以下是所提供的问题的解决方案。
import numpy as np
original = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
uniques, index = np.unique([str(i) for i in original], return_index=True)
cleaned = original[index]
print(cleaned)
将:
array([[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
把我的诺贝尔奖寄出去
让我们以列表的形式获取整个numpy矩阵,然后从这个列表中删除重复项,最后将我们唯一的列表返回到numpy矩阵中:
matrix_as_list=data.tolist()
matrix_as_list:
[[1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 0]]
uniq_list=list()
uniq_list.append(matrix_as_list[0])
[uniq_list.append(item) for item in matrix_as_list if item not in uniq_list]
unique_matrix=np.array(uniq_list)
unique_matrix:
array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 0]])
import numpy as np
original = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
# create a view that the subarray as tuple and return unique indeies.
_, unique_index = np.unique(original.view(original.dtype.descr * original.shape[1]),
return_index=True)
# get unique set
print(original[unique_index])