按'对数'方式拆分数组中的值 / 基于另一个数组进行拆分

5

我有一个二维数组,其中每个元素都是一个傅里叶变换。我想要对“对数级别”进行分割。例如,让我们取其中一个数组并将其称为a:

a = np.arange(0, 512)

# I want to split a into 'bins' defined by b, below:
b = np.array([0] + [10 * 2**i for i in range(6)]) # [0, 10, 20, 40, 80, 160, 320, 640]


我希望做的事情类似于使用np.split,但我想根据数组b将值分割成“桶”,使得所有a值在[0,10)之间的值都在一个桶中,所有值在[10,20)之间的值都在另一个桶中,以此类推。
我可以通过某种复杂的for循环来实现这个目标:
split_arr = []
for i in range(1, len(b)):
    fbin = []
    for amp in a:
        if (amp >= b[i-1]) and (amp < b[i]):
            fbin.append(amp)
    split_arr.append(fbin)

我有许多需要分割的数组,而且这种方式看起来很丑(仅代表我的个人观点)。是否有更好的方法?

2个回答

5

以下是使用 np.split 的方法:

np.split(a, np.searchsorted(a,b))

如果您的数组 a 没有排序,请在上述命令之前进行排序:
a = np.sort(a)

np.searchsorted函数能够找到要插入有序数组a的值在排序后数组b中的位置,也就是说,np.searchsorted函数可以找到分割数组的位置。如果你不想在开头得到一个空数组,只需从b中移除0即可。


刚刚计时了一下,速度飞快且简洁。我很高兴等了几分钟来查看答案。现在我正在文档中查找 np.searchsorted,因为我想更好地理解它。谢谢。 - rocksNwaves
@rocksNwaves 没关系。我添加了另一行以进行更多解释。希望有所帮助。如果它解决了你的问题,请随意接受答案。谢谢。 - Ehsan
所以这可能假设a在第一次排序时已经排好序了...这就是为什么它如此快速。如果a没有排序,那么您需要考虑排序的成本。仍然可能是最有效的方法,特别是对于大数组。 - Julien
@Julien 是的,谢谢您的留言。已添加到帖子中。 - Ehsan

1

首先,您可以通过使用列表推导式减少“丑陋”:

split_arr = [[amp for amp in a if (amp >= b[i-1]) and (amp < b[i])] for i in range(1, len(b))]

然后您可以使用numpy的快速并行功能应用相同的逻辑(这样做的好处是代码看起来更加简洁):

split_arr = [a[(a >= b[i-1]) & (a < b[i])] for i in range(1, len(b))]

比较:

%timeit [[amp for amp in a if (amp >= b[i-1]) and (amp < b[i])] for i in range(1, len(b))]
1.29 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit [a[(a >= b[i-1]) & (a < b[i])] for i in range(1, len(b))]
35.9 µs ± 4.52 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

我真的很想知道这个踩票的原因... - Julien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接