【问题标题】:MATLAB - Returning a matrix of sums of elements corresponding to the same kindMATLAB - 返回对应于同一种类的元素之和的矩阵
【发布时间】:2017-08-22 22:04:37
【问题描述】:

概述

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 循环没有任何想法。

感谢您的帮助。

【问题讨论】:

  • 注意:你应该使用.'转置矩阵,而不是复共轭转置'
  • 非常感谢您的编辑和建议。你是对的,我应该改用.',因为在输入包含复数的情况下我不需要任何共轭。
  • 没问题,我最终为您进行了编辑,但以后当您的文本中有代码时,请尝试使用 code formatting 而不是 粗体格式,这样可以事情清晰了很多

标签: matlab sum sumifs


【解决方案1】:

您可以使用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:如果您使用的是 R2015a 之前的 MATLAB 版本,则不会有 repelem。相反,您可以使用kron(或其他解决方案之一here)替换该行:

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

【讨论】:

  • 如果您没有repelem,请参阅here
  • @Jon:谢谢,我为此添加了注释。
  • 我的版本是 2016a,我有足够的内存,所以这个解决方案对我来说绝对没问题。您的解决方案简单高效。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 2023-03-25
  • 2013-03-14
  • 1970-01-01
相关资源
最近更新 更多