假设我有价值A = [20 35 50 57 78 90 105 120 143]
,B=[2 40; 45 80; 85 145];
A
是最大峰值的位置,B
是范围。
如何识别每个范围内的多个最大峰值?
我想要的答案是[2 3 4]
此外,我还想要一个包含相应峰值的酒窖peak
:
peak =
3 x 1 cell:
[20 35]
[50 57 78]
[90 105 120 143]
答案 0 :(得分:4)
A = [20 35 50 57 78 90 105 120 143];
B = [2 40; 45 80; 85 145];
C = zeros(size(B,1),1); % Initialise C
pks = cell(size(B,1),1); % Initalise peak value collector
for ii = 1:size(B,1)
pks{ii,1} = A(find(A>B(ii,1) && A<B(ii,2)));
C(ii,1) = numel(pks{ii,1});
end
C =
2 3 4
说明:
for
循环通过其行抓取B
。对于每一行,它使用第一列中的值作为下限阈值,将第二列中的值作为更高的阈值。数组A
中的值将根据此进行检查,并在单元数组pks
中收集。最后numel
只返回以这种方式找到的元素数量,并将其存储在C
。
我假设您将范围定义为 open 区间,即边界不属于该区间。另一方面,如果你想要关闭间隔,那么简单地使用它:
C(ii) = numel(find(A>=B(ii,1) & A<=B(ii,2)));
使用逻辑而不是find
的方法略快一些,这要归功于@rayryeng:
C = zeros(size(B,1),1); % Initialise C
for ii = 1:size(B,1)
tmp = A > B(ii,1) & A < B(ii,2);
pks{ii,1} = A(tmp);
C(ii,1) = sum(tmp);
end
这与上面大致相同,虽然速度更快。逻辑A > B(ii,1) & A < B(ii,2)
在区间内的每个位置放置1
,在所有其他位置放置0
。只需总结一下,你就得到了你想要的数字。这可以用作逻辑索引来获取A
的值。打开和关闭的时间间隔与上面相同。
答案 1 :(得分:3)
另一种方法是使用bsxfun
和permute
。我们可以做的是将其变成一个3D问题,其中每个切片告诉您B
中每个相应范围之间有多少个元素。你总结了每个切片的每一列:
%// Given
A = [20 35 50 57 78 90 105 120 143];
B = [2 40; 45 80; 85 145];
%// Create the 3D matrix we talked about
BL = permute(B(:,1), [2 3 1])
BR = permute(B(:,2), [2 3 1])
out = bsxfun(@ge, A, BL) & bsxfun(@le, A, BR);
%// Reshape output into a vector
vals = reshape(sum(out, 2), 1, []);
我们得到:
>> vals
vals =
2 3 4
答案 2 :(得分:3)
%// Mask of valid binning for A within the bins defined by the columns of B
mask = bsxfun(@ge,A(:),B(:,1).') & bsxfun(@le,A(:),B(:,2).')
%// Create interval version of A
A_intv = bsxfun(@times,mask,A(:))
A_intv(~mask) = nan
%// Get argmax for each bin
[~,max_mask_idx] = nanmax(A_intv,[],1)
%// Get start+1 indices for each bin
[~,start_idx] = max(mask,[],1)
%// Finally the output after subtracting start indices from max_mask_idx
out = max_mask_idx - (start_idx-1)