Pergunta

Eu tenho algum código que funciona, mas é um pouco de um gargalo, e eu estou preso tentando descobrir como acelerá-lo. É em um loop, e eu não consigo descobrir como vetorizar-lo.

Eu tenho uma matriz 2D, vals, que representa dados TimeSeries. As linhas são datas, as colunas são diferentes séries. Estou tentando balde os dados por meses para executar várias operações em que (soma, média, etc). Aqui está o meu código atual:

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 linha seguinte é o gargalo porque eu chamá-lo tantas vezes. (Looping)

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

Todas as idéias? Agradecemos antecipadamente.

Foi útil?

Solução

Isso é um problema difícil de vetorizar. Posso sugerir uma maneira de fazê-lo usando CELLFUN , mas eu não posso garantir que ele será mais rápido para o seu problema (você teria que tempo que se sobre os conjuntos de dados específicos que você está usando). Como discutido em esta outra questão SO , vectorizing não sempre trabalho mais rápido do que para loops. Ele pode ser específico problema, muito qual é a melhor opção. Com esse aviso legal, eu vou sugerir duas soluções para você tentar:. Uma versão CELLFUN e uma modificação de sua versão para-loop que pode correr mais rápido

CELLFUN SOLUÇÃO:

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

A chamada para MAT2CELL grupos as linhas de vals que têm a mesma data de início juntos em células de uma matriz de célula valCell . A variável newVals será uma matriz de células de comprimento Numel (uniqueStarts) , em que cada célula contém o resultado da execução de nansum na célula correspondente de valCell .

FOR-LOOP SOLUÇÃO:

[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

Outras dicas

Se tudo que você precisa fazer é formar a soma ou média em linhas de uma matriz, onde as linhas são somados dependendo outra variável (data), em seguida, usar a minha função consolidador. Ele é projetado para fazer exatamente esta operação, reduzindo dados com base nos valores de uma série de indicadores. (Na verdade, consolidador pode também trabalho em dados n-D, e com uma tolerância, mas tudo o que você precisa fazer é passar a informação mês e ano).

Localizar consolidador na troca de arquivos em Matlab Central

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top