MATLAB - 返回对应于同一种类的元素之和的矩阵

时间:2017-08-22 13:35:13

标签: matlab sum sumifs

概述

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

该函数返回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]';
  • 由于元素Date(2)Date(3)相同,我们有

    1. S(2,1)S(3,1)都等于A(2,1)A(3,1)的总和
    2. S(2,2)S(3,2)都等于A(2,2)A(3,2)的总和。
  • 由于元素Date(1)Date(7)Date(8)Date(9)相同,我们有

    1. S(1,1)S(7,1)S(8,1)S(9,1)等于A(1,1)A(7,1)A(8,1)的总和,A(9,1)

    2. S(1,2)S(7,2)S(8,2)S(9,2)等于A(1,2)A(7,2)A(8,2)的总和,A(9,2)

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循环的想法。

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

您可以使用accumarray执行此操作,但是您需要生成一组行和列下标到<? $a = array( array('id' => '1', 'name' => 'Milch','price' => '12'), array('id' => '2', 'name' => 'Reis','price' => '13'), array('id' => '3', 'name' => 'Öl','price' => '14'), array('id' => '4', 'name' => 'Salz','price' => '15'), array('id' => '5', 'name' => 'Zucker','price' => '16'), ); foreach ($a as $key => $value){ echo ( $value['name'] . ' ' . $value['price'] . PHP_EOL ); } ?> php select.php Milch 12 Reis 13 Öl 14 Salz 15 Zucker 16 才能执行此操作。以下是:

A

注意#1:这将使用比for循环解决方案更多的内存([~, ~, 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 将具有两倍于subs的元素数量,但可能会给你一个显着的加速。

注意#2:如果您使用的是早于R2015a的MATLAB版本,则您不会拥有repelem。相反,您可以使用kron(或其他解决方案之一here)替换该行:

A