【问题标题】:Stable accumarray in MATLABMATLAB 中的稳定 accumarray
【发布时间】:2015-04-12 08:38:36
【问题描述】:

MATLAB 的内置函数 accumarray 接受函数 fun 作为第四个参数。

A = accumarray(subs,val,sz,fun);

这会将fun 应用于val 中在subs 中具有相同下标的每个元素子集。然而,文档指出:

如果subs 中的下标未根据其线性索引进行排序,则fun 不应依赖于其输入数据中值的顺序。

我们如何实现accumarray稳定 版本,它没有此限制,但会保证子集采用与val 给出的相同顺序?

示例:

subs = [1:10,1:10];
val = 1:20;
accumarray(subs(:), val(:), [], @(x)x(end)).'

如果accumarray 稳定,则预期输出为11:20。实际上输出是:

ans =
    11    12    13    14     5     6     7    18    19    20

我们的实现应该产生:

accumarrayStable(subs(:), val(:), [], @(x)x(end)).'`
ans =
    11    12    13    14    15    16    17    18    19    20

【问题讨论】:

    标签: matlab accumarray stable-sort


    【解决方案1】:

    我们可以使用sortrows 作为预处理步骤,首先对索引和对应值进行排序,正如其文档所述:

    SORTROWS 使用 稳定 版本的快速排序。

    由于subs 中的下标应该根据它们的线性索引进行排序,我们需要按字典顺序对它们进行排序。这可以通过在使用sortrows 之前和之后翻转列顺序来实现。

    这为我们提供了accumarray 的稳定版本的以下代码:

    function A = accumarrayStable(subs, val, varargin)
    [subs(:,end:-1:1), I] = sortrows(subs(:,end:-1:1));
    A = accumarray(subs, val(I), varargin{:});
    

    替代方案:

    根据 Luis Mendo 的建议,也可以从下标生成线性索引并使用 sort 代替 sortrows

    function A = accumarrayStable(subs, val, varargin)
    if numel(varargin)>0 && ~isempty(varargin{1})
        sz = varargin{1};
    else
        sz = max(subs,[],1);
    end
    [~, I] = sort(subs*cumprod([1,sz(1:end-1)]).');
    A = accumarray(subs(I,:), val(I), sz, varargin{:});
    

    请注意,我们应该使用1+(subs-1)*cumprod([1,sz(1:end-1)]).' 来转换为线性索引。我们省略了+1-1,因为sort 的结果仍然相同;这为我们节省了几个周期。

    上述哪种解决方案更快取决于您的机器和 MATLAB 版本。例如,您可以通过以下方式进行测试:

    A = randi(10, 1e4, 5); 
    timeit(@()accumarrayStable(A(:,1:end-1), A(:,end), [], @(x)x(1))
    

    【讨论】:

    • 关于your comment,我打算建议sortrows(它也用于@Divakar's answer)。很好的问答!
    • @LuisMendo:我想有人可能会在某个时候需要这个,所以为什么不回答我自己的问题来改变一下。 :-)
    • 需要在输入到sortrows 之前反转索引,以便在线性索引意义上完成排序,对吧?也许您可以将其添加到您的答案中
    • @LuisMendo:我将添加第二个版本。似乎与我使用fun = @(x)x(end) 进行测试有关,无论出于何种原因,这会使版本2 的速度比版本1 慢得多......我们可能应该使用fun~=sum 的测试用例,否则稳定的东西不会无论如何都没有任何意义。
    • 现在我看到我收到了您关于 not 使用 sum 错误的评论 :-) 所以我们同意稳定性对于“非标准”函数是有意义的
    猜你喜欢
    • 2013-11-12
    • 2015-07-25
    • 2013-06-19
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 2019-09-15
    • 1970-01-01
    相关资源
    最近更新 更多