如何在python中有效地将带有条件的操作(如if)应用于大型numpy数组?

时间:2019-01-02 23:11:06

标签: python arrays numpy

大家下午好,我将原始数据放入numpy数组中,然后我想对数以10为底的对数数组执行“ if”运算,但是,这些numpy数组太大,因此它们需要一个很多时间来完成它们。

enter image description here

x = [ 20*math.log10(i) if i>0 and 20*math.log10(i)>=-60 else (-(120+20*math.log10(abs(i))) if i<0 and 20*math.log10(abs(i))>=-60 else -60) for i in a3 ]

在之前的代码中,我使用了从原始音频数据中抛出的一个channels数组“ a3”,并制作了另一个数组“ x”,其中包含一个数组,该数组的绘制范围为-120至0,在y边缘。此外,正如您所注意到的,我需要从numpy数组中分离出正的原始元素,而不是从numpy数组中分离出负的原始元素,并且还要将0s表示为-60,之后的操作为0。 enter image description here

此代码的问题是,正如我之前说的,大约需要10秒钟才能完成计算,而这仅适用于1个通道,并且我需要计算8个通道,因此我需要等待大约80个通道秒。

我想知道是否有一种更快的方法来执行此操作,此外,我发现了一种将numpy.log10应用于整个numpy数组的方法,它可以在不到两秒钟的时间内进行计算:

x = 20*numpy.log10(abs(a3))

但是我没有发现与使用ifs,条件或类似内容操纵该操作的首选项numpy.log10相关的任何信息。我确实需要确定负的和正的原始值以及0,然后将0显然转换为-60,使-60成为最小限制和参考点,就像我之前向您展示的代码一样。

注意:我已经尝试使用“ for”和“ while”之类的循环来完成此操作,但是它比实际方法花费更多的时间,例如每个14秒。

谢谢您的回应!

1 个答案:

答案 0 :(得分:0)

通常,在发布问题时,最好的做法是包括一个小的工作示例。我知道您提供了一张数据图片,但是其他人很难使用,因此最好只提供一小部分数据。这很重要,因为解决方案通常取决于数据。例如,您的所有数据(我认为)在-1和1之间,因此对数始终为负。如果不是这种情况,那么您的解决方案可能无法正常工作。

如果i>0为负数,则无需检查abs是否适用,然后应用i。这正是应用abs首先要做的。

您已经注意到,我们还可以使用numpy向量化来避免列表理解。像np.sin(X)这样的事情通常比[ np.sin(x) for x in X]更快。

最后,如果您在numpy中执行类似X>0的操作,它将返回一个布尔数组,说明每个元素是否为>0

请注意,编写列表理解的另一种方法是,首先采用20*math.log10(abs(i))并将所有值<-60替换为-60,然后在任何i<0处翻转数据约-60`。我们可以在向量化操作中做到这一点。

-120*(a3<0)+np.sign(a3)*np.maximum(20*np.log10(np.abs(a3)),-60)

由于a3<0np.sign(a3)做类似的事情,这可能可以优化一点。也就是说,我很确定这比列表理解要快。