3

accumarray()关于“subs”的第一个注释中,首次出现在 MATLAB R14sp3 文档中,说:

注意 如果 subs 中的下标没有排序, fun 不应该依赖于其输入数据中值的顺序。

我不清楚什么被认为是排序的。认为:

subs = [1 1
        2 1
        1 2
        2 2];
  1. 应该subs在某种意义上排序issorted(subs,'rows'),或者...
  2. 在线性索引意义上,即issorted(sub2ind([2 2],subs(:,1), subs(:,2)))

我想依靠:

accumarray(subs,val,[], @(x) x(end))

如果有人还可以提供来自旧版本的示例/测试(以检查向后兼容性),其中例如 1) 为假而 2) 为真,那就太好了。

PS。我对 的替代品大多不感兴趣accumarray,除非非常简洁并使用相同的subsand val

4

1 回答 1

3

好的,我做了一些测试,我认为引用中的“排序”是指线性索引意义上的。(如果重要的话,我在 R2013a 上)

为了理解如何accumarray调用指定的函数,我将通过指定要应用的函数来使用将值分组到单元数组中的技巧。fun = @(x) {x}

1) 一维索引

首先让我们创建一些下标和值

N = 10; sz = 4;
subs = randi([1 sz], [N 1]);
vals = (1:N)'*100;

现在我们在未排序的索引上调用 ACCUMARRAY(多次)

C = cell(5,1);
for i=1:5
    C{i} = accumarray(subs, vals, [], @(x){x});
end

传递给函数的值的顺序是任意的,但在多次运行中仍然是一致的:

>> assert(isequal(C{:}))
>> celldisp(C{1})
ans{1} =
   800
   900
   700
ans{2} =
   300
ans{3} =
        1000
         200
         100
ans{4} =
   400
   600
   500

这就是文档警告您fun不应依赖于传递给它的值的顺序的原因。

现在,如果我们预先对下标进行排序:

[~,ord] = sort(subs);
C = cell(5,1);
for i=1:5
    C{i} = accumarray(subs(ord), vals(ord), [], @(x){x});
end
assert(isequal(C{:}))
celldisp(C{1})

我们将看到这些值被传递给自己排序的函数:

ans{1} =
   700
   800
   900
ans{2} =
   300
ans{3} =
         100
         200
        1000
ans{4} =
   400
   500
   600

2) 二维索引

在 2D 下标索引的情况下,我尝试过同样的事情。首先我们从随机数据开始:

%# some 2d subscripts and corresponding values
N = 10; sz = 2;
subs = randi([1 sz], [N 2]);
vals = (1:N)*100;
  • 以下是未排序索引的情况:

    C = cell(5,1);
    for i=1:5
        C{i} = accumarray(subs, vals, [], @(x){x});
    end
    assert(isequal(C{:}))
    celldisp(C{1})
    
  • 这是我尝试“按行排序”的时候:

    [~,ord] = sortrows(subs, [1 2]);
    C = cell(5,1);
    for i=1:5
        C{i} = accumarray(subs(ord,:), vals(ord), [], @(x){x});
    end
    assert(isequal(C{:}))
    celldisp(C{1})
    
  • 最后是我们按“线性索引”排序的时候:

    [~,ord] = sort(sub2ind([sz sz], subs(:,1), subs(:,2)));
    C = cell(5,1);
    for i=1:5
        C{i} = accumarray(subs(ord,:), vals(ord), [], @(x){x});
    end
    assert(isequal(C{:}))
    celldisp(C{1})
    

我将省略长输出,并报告仅在最后一种情况下将值传递给函数ordered。所以我得出结论,“排序”标准是基于线性索引的。

ans{1,1} =
     []
ans{2,1} =
   200
   600
   700
ans{1,2} =
         100
         300
         400
         500
        1000
ans{2,2} =
   800
   900

奖金:

尝试改用以下函数:

function out = fun(x)
    out = {x};
    disp('[')
    disp(x)
    disp(']')
end

您会看到该函数以不可预知的方式被调用,即使有一些重复!您可能必须增加数据的大小才能看到这种行为......


就向后兼容性而言,文档在 MATLAB R14sp3中一直提到这个注释,但没有提到 R14sp2。鉴于它自2005 年以来已被记录在案,我会说依赖此功能是安全的(我怀疑任何使用此类旧版本的人都希望新代码能够正常工作!)

于 2013-07-08T23:16:34.693 回答