Domanda

Ho un codice che funziona, ma è un po 'di un collo di bottiglia, e mi sono bloccato cercando di capire come accelerarlo. E 'in un ciclo, e non riesco a capire come vettorizzare esso.

Ho un array 2D, vals, che rappresenta i dati timeseries. Le righe sono date, le colonne sono diverse serie. Sto cercando di benna i dati da mesi per eseguire varie operazioni su di esso (somma, media, ecc). Qui è il mio codice corrente:

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

Questa riga successiva è il collo di bottiglia, perché io lo chiamo così tante volte. (Looping)

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

Tutte le idee? Grazie in anticipo.

È stato utile?

Soluzione

Questo è un problema difficile da vettorizzare. Posso suggerire un modo per farlo utilizzando CELLFUN , ma non posso garantire che sarà più veloce per il vostro problema (che avrebbe dovuto tempo da soli sul set dati specifici che si sta utilizzando). Come discusso in quest'altra domanda SO , vettorializzazione non lo fa sempre il lavoro più velocemente rispetto per i cicli. Può essere molto problema specifico che è l'opzione migliore. Con quella dichiarazione di non responsabilità, io suggerisco due soluzioni per provare:. Una versione CELLFUN e una modifica del vostro versione per-loop che possono correre più veloce

CELLFUN SOLUZIONE:

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

La chiamata a MAT2CELL gruppi le righe di vals che hanno la stessa data di inizio insieme in cellule di una matrice di celle valCell . La variabile newVals sarà una matrice di celle di lunghezza Numel (uniqueStarts) , dove ogni cella contiene il risultato dell'esecuzione nansum sulla cella corrispondente di valCell .

FOR-LOOP SOLUZIONE:

[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

Altri suggerimenti

Se tutto quello che dovete fare è formare la somma o la media sulle righe di una matrice, in cui le righe sono sommati a seconda un'altra (data) variabile quindi utilizzare la mia funzione consolidatore. È stato progettato per fare esattamente questa operazione, riducendo dati in base ai valori di una serie indicatore. (In realtà, consolidatore può anche lavorare su dati di n-d, e con una tolleranza, ma tutto quello che dovete fare è passare l'informazione mese e anno).

Trova consolidatore sullo scambio di file su MATLAB Central

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top