PDA

查看完整版本 : 铲斗算法


poster
2019-12-10, 16:49
我有一些有效的代码,但是有点瓶颈,我一直在试图找出如何加快它的速度。这是一个循环,我无法弄清楚如何对其进行向量化。

我有一个2D数组vals,它代表时间序列数据。行是日期,列是不同的系列。我试图按月对数据进行存储分区以对其执行各种操作(求和,均值等)。这是我当前的代码:

allDts; %Dates/times for vals. Size is [size(vals, 1), 1] vals; [YM] = datevec(allDts); fomDates = unique(datenum(Y, M, 1)); %first of the month dates [YM] = datevec(fomDates); nextFomDates = datenum(Y, M, DateUtil.monthLength(Y, M)+1); newVals = nan(length(fomDates), size(vals, 2)); %preallocate for speed for k = 1:length(fomDates); 下一行是瓶颈,因为我已经多次调用它了。

idx = (allDts >= fomDates(k)) & (allDts < nextFomDates(k)); bucketed = vals(idx, :); newVals(k, :) = nansum(bucketed); end %for 有任何想法吗?提前致谢。


回答:
这是一个很难向量化的问题。我可以建议一种使用CELLFUN的方法 (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/cellfun.html) ,但是我不能保证它会更快地解决您的问题(您必须根据要使用的特定数据集自行计时)。正如在另一个SO问题中 (https://stackoverflow.com/questions/831721/turning-a-matlab-binary-matrix-into-a-vector-of-the-last-nonzero-index-in-a-fast)所讨论的,矢量化并不总是比for循环更快。这可能是非常特定于问题的,这是最佳选择。有了这个免责声明,我将为您推荐两种解决方案:CELLFUN版本和对for-loop版本的修改,可能会运行得更快。

CELLFUN解决方案:

[Y,M] = datevec(allDts); monthStart = datenum(Y,M,1); % Start date of each month [monthStart,sortIndex] = sort(monthStart); % Sort the start dates [uniqueStarts,uniqueIndex] = unique(monthStart); % Get unique start dates valCell = mat2cell(vals(sortIndex,:),diff([0 uniqueIndex])); newVals = cellfun(@nansum,valCell,'UniformOutput',false); 到呼叫MAT2CELL (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/mat2cell.html)基团具有相同的开始日期一起放入一个单元阵列valCell的细胞瓦尔斯的行。可变NEWVALS将长度numel(uniqueStarts),其中每个单元将含有关于valCell的对应的小区执行nansum的结果的单元阵列。

前循环解决方案:

[Y,M] = datevec(allDts); monthStart = datenum(Y,M,1); % Start date of each month [monthStart,sortIndex] = sort(monthStart); % Sort the start dates [uniqueStarts,uniqueIndex] = unique(monthStart); % Get unique start dates vals = vals(sortIndex,:); % Sort the values according to start date nMonths = numel(uniqueStarts); uniqueIndex = [0 uniqueIndex]; newVals = nan(nMonths,size(vals,2)); % Preallocate for iMonth = 1:nMonths, index = (uniqueIndex(iMonth)+1):uniqueIndex(iMonth+1); newVals(iMonth,:) = nansum(vals(index,:)); end

更多&回答... (https://stackoverflow.com/questions/863113)