Pregunta

Tengo un poco de código que funciona, pero es un poco de cuello de botella, y yo estoy atrapado tratando de averiguar la forma de acelerar.Es en un bucle, y no puedo entender cómo vectorizar ella.

Tengo una matriz 2D, vals, que representa unicc de datos.Las filas son las fechas, las columnas son diferentes de la serie.Estoy tratando de cubo de los datos por meses para realizar diversas operaciones en ella (suma, media, etc).Aquí está mi código actual:

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

Esta línea siguiente es el cuello de botella porque me llamo así muchas veces.(bucle)

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

Alguna Idea?Gracias de antemano.

¿Fue útil?

Solución

Esto es un problema difícil de vectorizar. Puedo sugerir una manera de hacerlo utilizando CELLFUN , pero no puedo garantizar que será más rápido para su problema (que tendría que usted mismo tiempo en los datos específicos establece que está utilizando). Como se discutió en esta otra cuestión de forma , vectorización no lo hace siempre trabajo más rápido que para los bucles. Puede ser muy problema específico que es la mejor opción. Con esa advertencia, voy a sugerir dos soluciones para que usted intente:. CELLFUN una versión y una modificación de la versión de bucle que puede correr más rápido

SOLUCIÓN 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);

La llamada a MAT2CELL agrupa las filas Vals que tienen la misma fecha de inicio juntos en células de un conjunto de celdas valCell . La variable newVals será una matriz de células de longitud Numel (uniqueStarts) , donde cada celda contendrá el resultado de realizar nansum en la celda correspondiente valCell .

for-loop SOLUCIÓN:

[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

Otros consejos

Si todo lo que usted necesita hacer es formar la suma o la media de las filas de una matriz donde las filas se suman dependiendo de otra variable (fecha), a continuación, utilizar mi consolidador de la función.Está diseñado para hacer exactamente esta operación, la reducción de los datos, basado en los valores de un indicador de la serie.(En realidad, consolidador también puede trabajar en la n-d datos, y con una tolerancia, pero todo lo que usted necesita hacer es pasar el mes y el año de la información.)

Encontrar consolidador en el intercambio de archivos en Matlab Central

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top