2013-02-03 125 views
4

我目前正在用python和numpy/scipy實現節拍檢測算法。 我基本上需要讀取.wav文件並對其進行處理。下面是代碼:成對映射numpy陣列

sampling_rate, wave_data = scipy.io.wavfile.read(argv[1]) 

wave_data是1 d numpy的陣列用約441 000的元件(10秒聲的以44.1KHz採樣率)。現在,我需要對這個數組中的每兩個元素進行一些基本的數學運算。這就是我現在的做法:

wave_data = [sampling_rate * (wave_data[i+1] - wave_data[i]) 
      for i in xrange(len(wave_data)-1)] 

這種運行需要很多時間(明顯沒有性能分析)。我需要將數組映射到「in-place」,而不創建新的python列表。我知道有numpy.vectorize,但我不知道如何配對映射(映射數組中的每兩個元素)。

回答

4

下列任一會做到這一點:

wave_date = sampling_rate * np.diff(wave_data) 

wave_date = sampling_rate * (wave_data[1:] - wave_data[:-1]) 

例如:

In [7]: sampling_rate = 2 

In [8]: wave_data = np.array([1, 3, 5, 2, 8, 10]) 

In [9]: sampling_rate * (wave_data[1:] - wave_data[:-1]) 
Out[9]: array([ 4, 4, -6, 12, 4]) 

就性能而言,這兩種方法都是關於比列表理解速度快500倍:

In [16]: wave_data = np.array([1., 3, 5, 2, 8, 10, 5, 2, 4, 7] * 44100) 

In [17]: %timeit sampling_rate * np.diff(wave_data) 
100 loops, best of 3: 2.2 ms per loop 

In [18]: %timeit sampling_rate * (wave_data[1:] - wave_data[:-1]) 
100 loops, best of 3: 2.15 ms per loop 

In [19]: %timeit [sampling_rate * (wave_data[i+1] - wave_data[i]) for i in xrange(len(wave_data)-1)] 
1 loops, best of 3: 970 ms per loop 
+1

我想你應該提到'wave_date [1:]'和'wave_date [: - 1]'會爲現有的數組創建視圖,因此它們不會消耗太多的內存。即使他們的差異確實創建了一個新的數組。 – Bakuriu

+0

工作讓我變成一個內存管理怪胎,所以我可能會用'wave_data [1:] - = wave_data [: - 1]; wave_data * = sampling_rate; wave_data = wave_data [: - 1]'因爲不需要創建數組,所以它實際上可能實際上速度更快。 – Jaime