Question

J'ai un code qui fonctionne, mais est un peu un goulot d'étranglement, et je suis coincé à essayer de comprendre comment l'accélérer. Il est dans une boucle, et je ne peux pas comprendre comment vectoriser.

J'ai un tableau 2D, vals, qui représente des données de séries chronologiques. Les lignes sont les dates, les colonnes sont différentes séries. Je suis en train de seau les données par mois pour effectuer diverses opérations sur elle (somme, moyenne, etc.). Voici mon code actuel:

allDts; %Dates/times for vals.  Size is [size(vals, 1), 1]
vals;
[Y M] = datevec(allDts);
fomDates = unique(datenum(Y, M, 1)); %first of the month dates

[Y M] = 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);

Cette ligne suivante est le goulot d'étranglement parce que je l'appelle tant de fois. (Looping)

    idx = (allDts >= fomDates(k)) & (allDts < nextFomDates(k));
    bucketed = vals(idx, :);
    newVals(k, :) = nansum(bucketed);
end %for

Des idées? Merci à l'avance.

Était-ce utile?

La solution

C'est un problème difficile à vectoriser. Je peux suggérer une façon de le faire en utilisant CELLFUN , mais je ne peux pas garantir que ce sera plus rapide pour votre problème (vous devez vous-même le temps sur les données spécifiques que vous utilisez définit). Comme indiqué dans cette autre question SO , vectorisation ne pas toujours travailler plus vite que pour les boucles. Il peut être très problème spécifique qui est la meilleure option. Avec cette mise en garde, je vous propose deux solutions pour vous d'essayer. Une version CELLFUN et une modification de votre boucle for version qui peut courir plus vite

CELLFUN SOLUTION:

[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);

L'appel à MAT2CELL regroupe les lignes vals qui ont la même date de début ainsi que dans les cellules d'un réseau de cellules valCell . La variable newVals est un réseau de cellules de longueur numel (uniqueStarts) , où chaque cellule contient le résultat de l'exécution Nansum sur la cellule correspondante valCell .

BOUCLE SOLUTION:

[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

Autres conseils

Si tout ce que vous devez faire est de former la somme ou moyenne sur les lignes d'une matrice, où les lignes sont additionnées selon une autre variable (date) puis utilisez ma fonction de consolidateur. Il est conçu pour faire exactement cette opération, ce qui réduit les données sur la base des valeurs d'une série d'indicateurs. (En fait, consolidateur peut aussi travailler sur des données n-d, et avec une tolérance, mais tout ce que vous devez faire est de transmettre l'information de mois et l'année.)

Trouver consolidateur sur l'échange de fichiers sur Central Matlab

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top