gpt4 book ai didi

python - 根据元素出现在另一个数组中的次数,删除 NumPy 数组中元素的最高效方法是什么?

转载 作者:行者123 更新时间:2023-12-04 00:00:33 29 4
gpt4 key购买 nike

假设我有两个 Numpy 数组:

a = np.array([1,2,2,3,3,3])
b = np.array([2,2,3])

我想从 a 中删除 b 中的所有元素,它们在 b 中出现的次数相同。即

diff(a, b)
>>> np.array([1,3,3])

请注意,对于我的用例,b 将始终是 a 的子集,并且两者都可能是无序的,但是像 numpy.setdiff1d 这样的类似集合的方法不会削减它,因为删除每个元素一定次数很重要。

我目前的懒惰解决方案如下:

def diff(a, b):
for el in b:
idx = (el == a).argmax()
if a[idx] == el:
a = np.delete(a, idx)
return a

但我想知道是否有更高效或更紧凑的“numpy-esque”编写方式?

最佳答案

这是基于 np.searchsorted 的矢量化方法-

import pandas as pd

def diff_v2(a, b):
# Get sorted orders
sidx = a.argsort(kind='stable')
A = a[sidx]

# Get searchsorted indices per sorted order
idx = np.searchsorted(A,b)

# Get increments
s = pd.Series(idx)
inc = s.groupby(s).cumcount().values

# Delete elemnents off traced back positions
return np.delete(a,sidx[idx+inc])

进一步优化

让我们在 groupby cumcount 部分使用 NumPy -

# Perform groupby cumcount on sorted array
def groupby_cumcount(idx):
mask = np.r_[False,idx[:-1]==idx[1:],False]
ids = mask[:-1].cumsum()
count = np.diff(np.flatnonzero(~mask))
return ids - np.repeat(ids[~mask[:-1]],count)

def diff_v3(a, b):
# Get sorted orders
sidx = a.argsort(kind='stable')
A = a[sidx]

# Get searchsorted indices per sorted order
idx = np.searchsorted(A,b)

# Get increments
idx = np.sort(idx)
inc = groupby_cumcount(idx)

# Delete elemnents off traced back positions
return np.delete(a,sidx[idx+inc])

基准测试

使用带有 10000 的设置~2x 的元素a 的重复次数和 ba 的一半大小.

In [52]: np.random.seed(0)
...: a = np.random.randint(0,5000,10000)
...: b = a[np.random.choice(len(a), 5000,replace=False)]

In [53]: %timeit diff(a,b)
...: %timeit diff_v2(a,b)
...: %timeit diff_v3(a,b)
108 ms ± 821 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
3.85 ms ± 53.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.89 ms ± 15.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

接下来,在 100000元素 -

In [54]: np.random.seed(0)
...: a = np.random.randint(0,50000,100000)
...: b = a[np.random.choice(len(a), 50000,replace=False)]

In [55]: %timeit diff(a,b)
...: %timeit diff_v2(a,b)
...: %timeit diff_v3(a,b)
4.45 s ± 20.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
37.5 ms ± 661 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
28 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

对于正数和排序输出

我们可以使用 np.bincount -

def diff_v4(a, b):
C = np.bincount(a)
C -= np.bincount(b,minlength=len(C))
return np.repeat(np.arange(len(C)), C)

关于python - 根据元素出现在另一个数组中的次数,删除 NumPy 数组中元素的最高效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62613826/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com