2

我有 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 新手,我很难知道要搜索哪些术语。

4

3 回答 3

3

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

r = accumarray(category,data,[],@(v) {(min(v)==v)});
r = vertcat(r{:});
groupminallrows = NaN(size(data));
groupminallrows(r) = data(r);
于 2014-07-05T17:02:22.027 回答
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-vector:

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

关于您的评论:

我假设原因是每个组中有多个最小值,然后find返回一个数组。要解决这个问题,您可以find(x == min(x))find(x == min(x),1). 但是你只会得到每组中每个最小值的第一次出现。

如果不希望这样做,我会说accumarray通常是错误的方法。

于 2014-07-05T13:45:12.337 回答
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

结果与上述相同。

于 2014-07-05T15:39:14.450 回答