numpy,取它们交集的数组差

numpy, taking array difference of their intersection

我有多个 numpy 数组,我想创建新的数组来做类似 XOR 的事情......但不完全是。

我的输入是两个数组,array1 和 array2。 我的输出是 array1.

的修改版本(或新数组,我不太在意)

修改是逐元素的,通过执行以下操作:

1.) 如果任一数组的给定索引为 0,则索引保持不变。 2.) 如果 array1 和 array2 不为零,则修改后的数组分配的值是 array1 的索引值减去 array2 的索引值,最小值为零。

示例:

array1:  [0, 3, 8, 0]
array2:  [1, 1, 1, 1]
output:  [0, 2, 7, 0]


array1:  [1, 1, 1, 1]
array2:  [0, 3, 8, 0]
output:  [1, 0, 0, 1]

array1:  [10, 10, 10, 10]
array2:  [8, 12, 8, 12]
output:  [2, 0, 2, 0]

我希望能够用一个 numpy.copyto 语句来做到这一点,但我不知道如何做。谢谢。

编辑:

它刚刚击中了我。我能做吗:

new_array = np.zeros(size_of_array1)
numpy.copyto(new_array, array1-array2, where=array1>array2)

编辑 2:由于我很快收到了几个答案,所以我将对不同的答案进行计时,看看它们的效果如何。几分钟后返回结果。

好的,结果在:

0 到 5 的随机整数数组,大小 = 10,000,10 个循环

1.)使用我的np.copyto方法

2.) 使用剪辑

3.) 使用最大值

0.000768184661865
0.000391960144043
0.000403165817261

Kasramvd 还在下面提供了一些有用的时序

In [73]: np.maximum(0,np.array([0,3,8,0])-np.array([1,1,1,1]))
Out[73]: array([0, 2, 7, 0])

这没有明确解决

If either array has 0 for the given index, then the index is left unchanged.

但所有示例的结果都匹配:

In [74]: np.maximum(0,np.array([1,1,1,1])-np.array([0,3,8,0]))
Out[74]: array([1, 0, 0, 1])
In [75]: np.maximum(0,np.array([10,10,10,10])-np.array([8,12,8,12]))
Out[75]: array([2, 0, 2, 0])

您可以使用简单的减法并将结果剪裁为零作为 min:

(arr1 - arr2).clip(min=0)

演示:

In [43]: arr1 = np.array([0,3,8,0]); arr2 = np.array([1,1,1,1])

In [44]: (arr1 - arr2).clip(min=0)
Out[44]: array([0, 2, 7, 0])

在大型阵列上,它也比 maximum 方法更快:

In [51]: arr1 = np.arange(10000); arr2 = np.arange(10000)

In [52]:  %timeit np.maximum(0, arr1 - arr2)
22.3 µs ± 1.77 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [53]: %timeit (arr1 - arr2).clip(min=0)
20.9 µs ± 167 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [54]: arr1 = np.arange(100000); arr2 = np.arange(100000)

In [55]:  %timeit np.maximum(0, arr1 - arr2)
671 µs ± 5.69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [56]: %timeit (arr1 - arr2).clip(min=0)
648 µs ± 4.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

请注意,如果 arr2 可能有负值,您应该考虑在 arr2 上使用 abs 函数以获得预期结果:

(arr1 - abs(arr2)).clip(min=0)

您可以先简单地减去数组,然后在减去的结果上使用 boolean array indexing 在有负值的地方分配 0,如:

# subtract
In [43]: subtracted = arr1 - arr2

# get a boolean mask by checking for < 0
# index into the array and assign 0
In [44]: subtracted[subtracted < 0] = 0

In [45]: subtracted
Out[45]: array([0, 2, 7, 0])

对 OP 指定的其他输入应用相同的方法:

In [46]: arr1 = np.array([1, 1, 1, 1])
    ...: arr2 = np.array([0, 3, 8, 0])

In [47]: subtracted = arr1 - arr2
In [48]: subtracted[subtracted < 0] = 0

In [49]: subtracted
Out[49]: array([1, 0, 0, 1])

对于第三个输入数组:

In [50]: arr1 = np.array([10, 10, 10, 10])
    ...: arr2 = np.array([8, 12, 8, 12])

In [51]: subtracted = arr1 - arr2
In [52]: subtracted[subtracted < 0] = 0

In [53]: subtracted
Out[53]: array([2, 0, 2, 0])