Matlab:如果索引在范围内,则求和相应的值 [英] Matlab: Sum corresponding values if index is within a range
问题描述
我一直在疯狂地试图找到一种加快速度的方法.现在,我当前的代码讨论了大约200秒,遍历了77000个事件.我希望有人可以帮助我加快速度,因为我必须做500左右.
I have been going crazy trying to figure a way to speed this up. Right now my current code talks ~200 sec looping over 77000 events. I was hoping someone might be able to help me speed this up because I have to do about 500 of these.
问题: 我有两个数组(均为200000x1),它们对应于77000个事件中命中的能量和位置.我将每个事件的范围分为两个数组,event_start和event_end.我要做的第一件事是在特定范围内寻找位置,然后将对应的能量放入其自己的数组中.为了从这些信息中获取所需信息,我循环浏览每个事件及其对应的开始/结束,以总结每个事件所产生的所有能量.我的代码如下:
Problem: I have arrays (both 200000x1) that correspond to Energy and Position of a hit over 77000 events. I have the range of each event separated into two arrays, event_start and event_end. First thing I do is look for the position in a specific range, then I put the correspond energy in its own array. To get what I need out of this information, I loop through each event and its corresponding start/end to sum up all the energies from each it hit. My code is below:
indx_pos = find(pos>0.7 & pos<2.0);
energy = HitEnergy(indx_pos);
for i=1:n_events
Etotal(i) = sum(energy(find(indx_pos>=event_start(i) …
& indx_pos<=event_end(i))));
end
样本输入和输出:
% Sample input
% pos and energy same length
n_events = 3;
event_start = [1 3 7]';
event_end = [2 6 8]';
pos = [0.75 0.8 2.1 3.6 1.9 0.5 21.0 3.1]';
HitEnergy = [0.002 0.004 0.01 0.0005 0.08 0.1 1.7 0.007]';
% Sample Output
Etotal = 0.0060
0.0800
0
推荐答案
方法1:一般情况
使用 bsxfun
和matrix-multiplication
的一种方法-
mask = bsxfun(@ge,indx_pos,event_start.') & bsxfun(@le,indx_pos,event_end.')
Etotal = energy.'*mask
如果indx_pos
中包含很多元素,则可能有点memory-hungry
.
This could be a bit memory-hungry
if indx_pos
has lots of elements in it.
方法2:开始/结束范围不重叠的情况
对于这种特殊情况,可以使用 accumarray
-
One can use accumarray
for this special case like so -
%// Setup ID array for use in accumarray later on
loc(numel(pos))=0; %// Fast pre-allocation scheme
valids = event_end+1<=numel(pos);
loc(event_end(valids)+1) = -1*(1:sum(valids));
loc(event_start) = loc(event_start)+(1:numel(event_end));
id = cumsum(loc);
%// Set elements as zeros in HitEnergy that do not satisfy the criteria:
%// pos>0.7 & pos<2.0
HitEnergy_select = (pos>0.7 & pos<2.0).*HitEnergy(:);
%// Discard elments in HitEnergy_select & id that have IDs as zeros
HitEnergy_select = HitEnergy_select(id~=0);
id = id(id~=0);
%// Accumulate summations as done inside the loop in the original code
Etotal = accumarray(id(:),HitEnergy_select);
这篇关于Matlab:如果索引在范围内,则求和相应的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!