乐趣取决于潜艇的次序和值的顺序

时间:2013-07-08 21:47:21

标签: matlab grouping accumulate accumarray

accumarray()关于'subs'的第一个注释,首先出现在MATLAB R14sp3 docs中,说:

  

注意如果未对subs中的下标进行排序,则乐趣不应取决于其输入数据中值的顺序。

我不清楚什么被认为是分类的。假设:

subs = [1 1
        2 1
        1 2
        2 2];
  1. subs应按issorted(subs,'rows')或......
  2. 排序
  3. linear indexing 意义上,即issorted(sub2ind([2 2],subs(:,1), subs(:,2)))
  4. 我想依靠:

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

    如果某人还可以提供旧版本的示例/测试(以检查向后兼容性),例如1)是假的,而2)是真的,那将是伟大的。

    PS。我对accumarray的替代品不感兴趣,除非非常简洁且使用相同的subsval

1 个答案:

答案 0 :(得分:3)

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

要了解accumarray如何调用指定的函数,我将使用trick将值分组到cellarray中,方法是将fun = @(x) {x}指定为要应用的函数。

1)1D指数

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

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

我在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})
    
  • 这是我尝试"sorting by rows"的时候:

    [~,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})
    
  • 最后,我们按"linear index"排序:

    [~,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以来已被记录,我认为依赖此功能是安全的(我怀疑任何使用这些旧版本的人都希望新代码能够正常工作!)