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

Matlab 使用accumarray和@min从组中提取min,但也从另一个变量/列中输出相应的值,matlab,min,accumarray,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

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

与自定义函数一起使用:

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通常是错误的选择。

尝试以下解决方案:

% 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;
% 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);
结果向量:

>> 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

编辑: 以下是另一种解决方案:

% 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;
% 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
中提取第二个输出参数:

米纳格
结果与上面相同。

如果同一类别的所有数据都在一次运行中,并且类别已排序,则此操作有效,如您的示例所示。每个类别中允许有几个最小值

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

谢谢这在我为简单起见提供的“测试”数据和实际数据集的小块数据中非常有效,但当我对所有820000行实际数据进行测试时,命令groupidx=accumarray(category,data,[],@(x)find(x==min(x))。”返回错误消息:“使用accumarray函数时出错”@(x)find(x==min(x))“返回了一个非标量值。”我想这是因为我的“数据”中有一些N。有什么想法吗?谢谢,我们走的路。对于我的实际数据集,即使有“find(x==min(x),1)”,我仍然会得到一个“returned a non-scalar value”错误。。。到目前为止,Amro的代码似乎对我有用。。。非常感谢你的帮助!感谢Amro,这似乎与我的实际数据集配合得很好(我仍在阅读以了解这些命令实际上在做什么!)。但是,“断言”命令每次都会报告“断言失败”。我应该担心吗?当绘制数据时,数据看起来是正确的,并且绘制在正确的位置……据我所知,数据中有很多NaN值,因此尝试将上面的
isequal
替换为
isequaln
(因为如果一个类别只包含NaN值,那么最小值也是
NaN
,并且您可能知道我们无法比较NaN是否相等,您需要特殊的
isequaln
或旧的
IseQualWithEqualNaN
)太好了!isequalwithnans附带的错误消息-我似乎有一个旧版本的Matlab。非常感谢您的帮助!很高兴我能提供帮助。我应该提到的一点是,
category
必须在调用之前进行排序,否则您必须自己明确地进行排序(别忘了对相应的
数据
值进行排序以匹配它)。这是因为我们依赖于顺序的确定性。您可以在此处阅读此详细信息:哇-这只需4行即可实现我所需的功能-现在来了解它的实际功能!谢谢!@Jo查看中间结果,并询问我是否需要。关键是
accumarray
中的匿名函数,它返回包含矢量的电池仍然在学习这个系统。路易斯·门多的建议和阿姆罗的建议都很有效,但前者似乎更简单。