我有两个numpy数组a
和b
,有两千万个元素(浮点数)。如果这两个数组的组合元素相同,那么我们称之为重复,应该从两个数组中删除。例如,
a = numpy.array([1,3,6,3,7,8,3,2,9,10,14,6])
b = numpy.array([2,4,15,4,7,9,2,2,0,11,4,15])
从这两个数组中,我们a[2]&b[2]
与a[11]&b[11]
相同,然后我们将其称为重复元素,应将其删除。与a[1]&b[1]
vs a[3]&b[3]
相同虽然每个数组本身都有重复元素,但它们不会被视为重复元素。所以我希望返回的数组是:
a = numpy.array([1,3,6,7,8,3,2,9,10,14])
b = numpy.array([2,4,15,7,9,2,2,0,11,4])
任何人都有最聪明的方法来实现这种减少吗?
答案 0 :(得分:3)
首先,您必须打包a
和b
以识别重复项。
如果值是正整数(参见其他情况下的编辑),则可以通过以下方式实现:
base=a.max()+1
c=a+base*b
然后只需在c
中找到唯一值:
val,ind=np.unique(c,return_index=True)
并检索a
和b
中的相关值。
ind.sort()
print(a[ind])
print(b[ind])
重复的删除。 (这里有两个):
[ 1 3 6 7 8 3 2 9 10 14]
[ 2 4 15 7 9 2 2 0 11 4]
修改强>
无论数据类型如何,c数组都可以如下所示,将数据打包为字节:
ab=ascontiguousarray(vstack((a,b)).T)
dtype = 'S'+str(2*a.itemsize)
c=ab.view(dtype=dtype)
答案 1 :(得分:2)
这是在一次通过中完成的,并且不需要任何额外的内存用于生成的数组。
将每个索引处的元素配对并迭代它们。跟踪到目前为止已经看到哪些对以及数组索引的计数器。如果以前没有看到新的对,则索引将增加1,有效地将它们写回原始位置。但是,对于重复对,您不会增加索引,有效地将每个新对转移到左侧一个位置。最后,保留第一个index
个元素以缩短数组。
import itertools as it
def delete_duplicate_pairs(*arrays):
unique = set()
arrays = list(arrays)
n = range(len(arrays))
index = 0
for pair in it.izip(*arrays):
if pair not in unique:
unique.add(pair)
for i in n:
arrays[i][index] = pair[i]
index += 1
return [a[:index] for a in arrays]
如果您使用的是Python 2,zip()
会预先创建对列表。如果阵列中有很多元素,那么使用itertools.izip()
会更有效率,这会在您请求时创建对。但是,默认情况下,Python 3中的zip()
的行为与此类似。
对于您的情况,
>>> import numpy as np
>>> a = np.array([1,3,6,3,7,8,3,2,9,10,14,6])
>>> b = np.array([2,4,15,4,7,9,2,2,0,11,4,15])
>>> a, b = delete_duplicate_pairs(a, b)
>>> a
array([ 1, 3, 6, 7, 8, 3, 2, 9, 10, 14])
>>> b
array([ 2, 4, 15, 7, 9, 2, 2, 0, 11, 4])
现在,这一切都归结为数组所拥有的值。如果您只有0-9的值,则只有100个唯一对,大多数元素将是重复的,这样可以节省您的时间。对于a
和b
的2000万个元素并且仅包含0-9之间的值,该过程在6秒内完成。对于0-999之间的值,需要12秒。