我有一个约1.5亿分的时间序列。我需要放大300万点。也就是说,我需要在这个1.5亿点时间序列中提取围绕这300万个感兴趣区域的100个时间点。
尝试:
def get_waveforms(data,spiketimes,lookback=100,lookahead=100):
answer = zeros((len(spiketimes),(lookback+lookahead)))
duration = len(data)
for i in xrange(len(spiketimes)):
if(spiketimes[i] - lookback) > 0 and spiketimes[i] + lookahead) < duration:
answer[i,:] = data[(spiketimes[i]-lookback):(spiketimes[i]+lookahead)]
return answer
这会占用我Mac上的所有可用内存。如果我尝试传递len(array) > 100000
的数组,它会爆炸。是否有更高效的内存或(希望)更优雅的方法来基于另一个阵列拉出一个阵列的部分?
相关 This答案是相关的。但是,我不确定如何应用它并避免循环。我是否有效地使用布尔矩阵的列来反复索引时间序列向量?
答案 0 :(得分:1)
您正在分配200 * len(spiketimes)
个浮点数组,因此对于您的100,000个项spiketimes
应该只有160 MB左右,这看起来并不多。另一方面,如果你去1,000,000 spiketimes
,1.6 GB单阵列可能是某些系统的延伸。如果你有记忆,你可以用这样的东西来矢量化提取:
def get_waveforms(data, spiketimes, lookback=100, lookahead=100) :
offsets = np.arange(-lookback, lookahead)
indices = spiketimes + offsets[:, None]
ret = np.take(data, indices, mode='clip')
ret[:, spiketimes < lookback] = 0
ret[:, spiketimes + lookahead >= len(data)] = 0
return ret
spiketimes
太靠近data
边缘的处理模仿了你的函数中的循环。
当您拥有如此多的数据时,明智之举就是将视图带入其中。这很难进行矢量化(或者至少我没有想过如何),但由于你没有复制任何数据,所以python循环不会慢得多:
def get_waveforms_views(data, spiketimes, lookback=100, lookahead=100) :
ret = []
for j in spiketimes :
if j < lookback or j + lookahead >= len(data) :
ret.append(None)
else :
ret.append(data[j - lookback:j + lookahead])
return ret
使用以下测试数据:
data_points, num_spikes = 1000000, 10000
data = np.random.rand(data_points)
spiketimes = np.random.randint(data_points, size=(num_spikes))
我得到了这些时间:
In [2]: %timeit get_waveforms(data, spiketimes)
1 loops, best of 3: 320 ms per loop
In [3]: %timeit get_waveforms_views(data, spiketimes)
1 loops, best of 3: 313 ms per loop