matlab - 乐趣取决于潜艇的顺序和 accumarray 中的值

标签 matlab grouping accumulate accumarray

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

Note If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data.

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

subs = [1 1
        2 1
        1 2
        2 2];
  1. subs 是否应该按issorted(subs,'rows') 的方式排序,或者...
  2. linear indexing 意义,即 issorted(sub2ind([2 2],subs(:,1), subs(:,2)))

我想依靠:

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

如果有人还可以提供旧版本的示例/测试(以检查向后兼容性),例如1) 是错误的,而 2) 是正确的,那就太好了。

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

最佳答案

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

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

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})
    
  • 这是我尝试的时候 "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 以来已被记录在案。 ,我会说依赖此功能是安全的(我怀疑任何使用此类旧版本的人都希望新代码无论如何都能正常工作!)

关于matlab - 乐趣取决于潜艇的顺序和 accumarray 中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17536558/

相关文章:

java - 在Java中访问dll文件

javascript - 如何包装所有相邻且具有相同类的元素?

powershell - 如何使用PowerShell按日期对文件进行分组?

recursion - 使用递归累积列表时出现类型错误

matlab - 如何在 MEX 函数中读取整数数组

arrays - MATLAB:如何拆分不同分隔符数字的元胞数组?

matlab - 在 MATLAB 中使用 SVM 实现 HOG 特征

java - java 8中的Group By具有多级分组

string - 为什么在尝试将字符串添加到此字符串的末尾时,haskell 会停止?

c++ - 如何使用 std::accumulate 和 lambda 计算平均值?