使用accumarray和@min从组中提取min,但也从另一个变量/列输出相应的值

时间:2014-07-05 13:29:37

标签: matlab min accumarray

我有3列数据:

time     = [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16];
category = [1;1;1;1;2;2;2;2;3; 3; 3; 3; 4; 4; 4; 4];
data     = [1;1;0;1;2;2;1;2;3; 3; 2; 3; 4; 4; 4; 3];

我使用以下内容来提取每个类别的最小数据值:

groupmin = accumarray(category,data,[],@min)

哪个输出:

groupmin = [0;1;2;3]

但是,我真的希望有一个输出也告诉我最小值来自哪个时间点,例如

timeofgroupmin  = [3;7;11;16]
groupmin        = [0;1; 2; 3]

或者,我希望在自己的向量中输出最小值,其中任何行的NaN都不是其最小值,例如。

groupminallrows = [NaN;NaN;0;NaN;NaN;NaN;1;NaN;NaN;NaN;2;NaN;NaN;NaN;NaN;3];

任何一种方法都可以解决我的问题。作为一名Matlab新手,我很难知道要搜索哪些术语。

3 个答案:

答案 0 :(得分:3)

如果同一类别的所有数据都在一次运行中并且类别已按照示例排序,则此方法有效。每个类别中允许使用几个最小化器。

r = accumarray(category,data,[],@(v) {(min(v)==v)});
r = vertcat(r{:});
groupminallrows = NaN(size(data));
groupminallrows(r) = data(r);

答案 1 :(得分:1)

accumarray与自定义功能结合使用:

time     = [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16];
category = [1;1;1;1;2;2;2;2;3; 3; 3; 3; 4; 4; 4; 4];
data     = [1;1;0;1;2;2;1;2;3; 3; 2; 3; 4; 4; 4; 3];

groupmin = accumarray( A(:,1), A(:,2), [], @min)

你拥有的是什么,但要获得最小值的指数和他们的时间,你需要min函数的第二个输出,我不知道是否可以与accumarray一起使用时获得。但是有以下解决方法:

groupidx = accumarray( category, data, [], @(x) find(x == min(x) )).'
occ = cumsum(hist(category,unique(category)))
idx = -occ(1)+occ+groupidx;
timeofgroupmin = time(idx).'
groupmin = data(idx).'

groupmin =

     0     1     2     3

timeofgroupmin =

     3     7    11    16

您想要的NaN - 矢量:

groupminallrows = NaN(1,numel(data));
groupminallrows(idx) = data(idx)

关于你的评论:

我假设的原因是,每组中有多个最小值,然后find返回一个数组。要解决此问题,您可以将find(x == min(x))替换为find(x == min(x),1)。但是你会在每组中首先出现每个最小值。

如果不需要,我说accumarray通常是错误的方法。

答案 2 :(得分:1)

试试这个解决方案:

% first we group the data into cell according to the group they belong to
grouped = accumarray(category, data, [], @(x){x});

% find the minimum and corresponding index of each group
[mn,idx] = cellfun(@min, grouped);

% fix index by offsetting the position to point the whole data vector
offset = cumsum([0;cellfun(@numel, grouped)]);
idx = idx + offset(1:end-1);

% result
[mn(:) idx(:)]
assert(isequal(mn, data(idx)))

% build the vector with NaNs
mnAll = nan(size(data));
mnAll(idx) = mn;

得到的载体:

>> mn'
ans =
     0     1     2     3
>> idx'
ans =
     3     7    11    16
>> mnAll'
ans =
   NaN   NaN     0   NaN   NaN   NaN     1   NaN   NaN   NaN     2   NaN   NaN   NaN   NaN     3

编辑:

这是另一种解决方案:

% find the position of min value in each category
idx = accumarray(category, data, [], @minarg);

% fix position in terms of the whole vector
offset = cumsum([0;accumarray(category,1)]);
idx = idx + offset(1:end-1);

% corresponding min values
mn = data(idx);

我正在使用以下自定义函数从min中提取第二个输出参数:

minarg.m

function idx = minarg(X)
    [~,idx] = min(X);
end

结果与上述相同。