问题
I can quickly apply a cos function as follows to a float32 numpy array:
cos_f = np.vectorize(lambda x: math.cos(2 * math.pi * x))
signal = square_f(integral)
However if I try this:
square_f = np.vectorize(lambda x: sig.square(2 * math.pi * x))
signal = square_f(integral)
it takes 15 seconds for 60,000 samples. integral
has a length of 1024 and is used as a buffer.
How should I be applying the square wave to my signal?
回答1:
sig.square(2*np.pi * x)
is three times slower than np.cos(2*np.pi * x)
, however, this is not a bottleneck here. This nice np.vectorize
- based decoration actually costs 120x slowdown! The reason why this happens is that square_f
applies scipy.signal.square
on items being iterated which is a bunch of aritmetics designed to work with arrays instead (unlike math.cos
). This is an example of arithmetics done inside scipy.signal.square
:
def example(x, w=0.5):
return (1 - (w > 1) | (w < 0)) & (np.mod(x, 2 * pi) < w * 2 * np.pi)
Assuming arr
is a large array, this is obviously more efficient to call example(arr)
instead of
ex = np.vectorize(lambda x: example(x))
ex(arr)
The timings show that as well:
arr = np.linspace(0,1,1000000)
%timeit ex(arr)
%timeit example(arr)
8.13 s ± 208 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
18.5 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
回答2:
I am not sure you need the np.vectorize
here at all:
import numpy as np
from scipy import signal as sig
integral = np.linspace(0, 10, 1024)
signal1 = np.cos(2*np.pi * integral)
signal2 = sig.square(2*np.pi * integral)
You can of course also create a function and than call it with an array as input:
def cos2pi(x):
return np.cos(2*np.pi * x)
signal1 = cos2pi(integral)
And one could go even further and call the function just once for all samples simultaneously.
samples = np.random.random((60000, 1024))
signal1 = cos2pi(samples)
来源:https://stackoverflow.com/questions/64082859/apply-square-wave-function-to-numpy-array