概述
n×m
矩阵A
和n×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)
相同,我们有
S(2,1)
和S(3,1)
都等于A(2,1)
和A(3,1)
的总和S(2,2)
和S(3,2)
都等于A(2,2)
和A(3,2)
的总和。由于元素Date(1)
,Date(7)
,Date(8)
和Date(9)
相同,我们有
S(1,1)
,S(7,1)
,S(8,1)
,S(9,1)
等于A(1,1)
,A(7,1)
,A(8,1)
的总和,A(9,1)
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) = 7
和S(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
我使用A
和Date
在我的计算机上测试了这些属性:
size(A) = [33055 400];
size(Date) = [33055 1];
length(unique(Date)) = 2645;
我的电脑用了大约1.25秒才完成任务。
这个任务在我的项目中执行了数十万次,因此我的代码太耗时了。如果我能消除上面的for循环,我认为性能会提升。
我找到了一些内置函数,它们执行特殊类型的求和,如accumarray
或cumsum
,但我仍然没有任何关于如何消除for循环的想法。
感谢您的帮助。
答案 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