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