MATLAB - 返回对应于同类元素的总和矩阵

MATLAB - Returning a matrix of sums of elements corresponding to the same kind

概览

一个n×m矩阵A和一个n×1向量Date是函数S = sumdate(A,Date)的输入。

函数 returns 一个 n×m 向量 S 使得 S 中的所有行对应于相同的 A 行的总和日期。

例如,如果

A = [1  2  7  3  7  3  4  1  9
     6  4  3  0 -1  2  8  7  5]';
Date = [161012 161223 161223 170222 160801 170222 161012 161012 161012]';

那么我希望返回的矩阵 S

S = [15 9 9 6 7 6 15 15 15;
    26 7 7 2 -1 2 26 26 26]';

S([4,6],1)S([4,6],2)

相同

由于元素Date(5)不重复,所以S(5,1) = A(5,1) = 7S(5,2) = A(5,2) = -1.


到目前为止我写的代码

这是我尝试完成此任务的代码。

function S = sumdate(A,Date)
    S = A; %Pre-assign S as a matrix in the same size of A.
    Dlist = unique(Date); %Sort out a non-repeating list from Date
    for J = 1 : length(Dlist)
        loc = (Date == Dlist(J)); %Compute a logical indexing vector for locating the J-th element in Dlist
        S(loc,:) = repmat(sum(S(loc,:)),sum(loc),1); %Replace the located rows of S by the sum of them
    end
end

我在我的电脑上使用 ADate 测试了它,这些属性:

size(A) = [33055    400];
size(Date) = [33055    1];
length(unique(Date)) = 2645;

我的电脑执行该任务大约需要 1.25 秒。

这个任务在我的项目中执行了数十万次,因此我的代码太耗时了。我认为如果我能消除上面的 for 循环,性能会得到提升。

我发现了一些内置函数可以执行特殊类型的求和,例如 accumarraycumsum,但我仍然不知道如何消除 for 循环。

非常感谢您的帮助。

您可以使用 accumarray 执行此操作,但您需要在 A 中生成一组行和列下标才能执行此操作。方法如下:

[~, ~, index] = unique(Date);  % Get indices of unique dates
subs = [repmat(index, size(A, 2), 1) ...         % repmat to create row subscript
        repelem((1:size(A, 2)).', size(A, 1))];  % repelem to create column subscript
S = accumarray(subs, A(:));    % Reshape A into column vector for accumarray
S = S(index, :);               % Use index to expand S to original size of A

S =

    15    26
     9     7
     9     7
     6     2
     7    -1
     6     2
    15    26
    15    26
    15    26

注意 #1: 这将使用比 for 循环解决方案更多的内存(subs 的元素数量是 A 的两倍),但可能会给你显着的加速。

注#2:如果您使用的 MATLAB 版本早于 R2015a,则不会有 repelem. Instead you can replace that line using kron (or one of the other solutions here):

kron((1:size(A, 2)).', ones(size(A, 1), 1))