你可以通过欺骗使匿名函数输出一个
单元格数组而不是一个单一的值。这样,
accumarray
将给你一个矩阵的单元格数组。然后,当你完成时,你可以将所有的矩阵连接成一个单一的矩阵。请注意,你提出的匿名函数具有min、max和mean作为一行向量,但你期望的结果是一个
列向量。因此,在匿名函数内部我进行了转置。
我们需要考虑到的问题是填充值。你指定的填充值需要是一个标量。因此,你可以通过留空来欺骗,但是你的输出现在将包含单元格中的空矩阵,而不是用0填充结果的行。解决这个问题的方法是找到所有为空的单元格,用一行零替换它们,然后在完成时将它们全部拼接在一起。要确定
accumarray
输出的哪些行将为空,你可以使用
cellfun
和
isempty
,这样我们就可以看到结果中哪些元素是空的。更简洁的方法是首先预分配一个
zeros
矩阵,然后只填充与
accumarray
输出的非空位置相对应的行以完成它:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
out = accumarray(subs, vals, [], @(x){[min(x),mean(x),max(x)].'});
ind_empty = cellfun('isempty', out);
out_final = zeros(3, numel(out));
out_final(:, ~ind_empty) = cat(2, out{:});
请注意使用
cat
,它将矩阵在指定维度上连接起来。执行
out{:}
会生成一个称为
逗号分隔列表的内容,因此相当于将
accumarray
输出的每一列作为单独的参数放入
cat
中,最终将所有列拼接成一个单独的矩阵,但是我按照某种方式切片输出,只填充未空的位置。
通过您的测试输入,我得到了与您相同的结果:
>> out_final
out_final =
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
然而,如果我可以坦诚地说 - 如果你确定只有三个值要分组到accumarray
中,那么直接调用三次可能会更快,然后在完成后将所有内容连接起来。我认为这种方法更易读,并且清楚地表明了你正在做什么。使用上述单元格数组的方式需要你真正了解MATLAB的工作原理。
stats = regionprops(subs, vals,'MaxIntensity','MeanIntensity','MinIntensity')
。由于你说实际的 accumarray 函数与 min/mean/max 很不同,因此 regionprops 也无法帮助到你。 - rahnema1