2009-05-14 6 views
3

내가 병목 현상을 조금 작동하지만 일부 코드를 가지고, 나는 그것을 빠르게하는 방법을 알아 내려고 붙어있어. 그것은 반복적이며, 벡터화하는 방법을 이해할 수 없습니다.버킷 팅 알고리즘

나는 시계열 데이터를 나타내는 2 차원 배열, 발스을 가지고있다. 행은 날짜이고, 열은 시리즈와 다릅니다. 나는 그것에 대한 다양한 작업 (합계, 평균 등)을 수행하기 위해 데이터를 몇 달에 걸쳐 버킷하려고합니다. 여기에 내 현재 코드입니다 : 내가 그렇게 여러 번 호출하기 때문에

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

이 다음 줄은 병목 현상 (루프)

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

어떤 아이디어.? 미리 감사드립니다.

+0

이가 수행해야합니다 사용 ['accumarray'] (https://www.mathworks.com/help/matlab/ref/accumarray.html) ... –

답변

2

벡터 라이팅하는 것은 어려운 문제입니다. CELLFUN을 사용하여이를 수행 할 수있는 방법을 제안 할 수는 있지만 문제가 더 빠를 것이라고 보장 할 수는 없습니다 (사용중인 특정 데이터 세트에서 직접 시간을 측정해야합니다). this other SO question에서 설명했듯이 벡터화는 이 아니며 항상이 루프보다 빠르게 작동합니다. 그것은 가장 좋은 옵션 인 매우 특정한 문제 일 수 있습니다. 이 면책 조항을 통해 두 가지 해결책, 즉 CELLFUN 버전과 for 루프 버전의 수정을 제안합니다.

CELLFUN 해결책 : 발스 세포 배열 valCell 세포에 함께 동일한 시작일이

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

통화 그룹 MAT2CELL로 행. 가변 newVals 각 셀 의 해당 셀에 valCellnansum을 수행 한 결과를 포함 길이 numel (uniqueStarts)의 세포 배열 될 것이다.

FOR-LOOP 해결책 :

[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 
+0

고마워요. 이것은 약 50 % 속도! 코드를 올바르게 이해하면 다음 줄이 나타납니다. valCell = mat2cell (vals, diff ([0; uniqueIndex])); 이 키입니다.이 값은 셀로 값을 나눕니다. 즉, 두 번째 arg 길이가 길어집니다. (정렬을 필요로하지 않았다. 날짜와 관련 값은 – Marc

+0

종류로 보장된다. 당신이 가지고있는 것처럼 들리지만, MAT2CELL의 두 번째 인수는 첫 번째 인수의 행이 될 크기의 벡터이다. 예를 들어, 첫 번째 인수가 6x3 행렬 (A)이고 두 번째 인수가 [1 2 3]이면 MAT2CELL은 다음과 같은 3 요소 셀 배열 (B라고 함)을 반환합니다. B = {A (1, :); A (2 : 3, :); A (4 : 6, :)} – gnovice

0

당신이 합을 형성하거나 행이 다른 변수 (날짜)에 따라 합산 행렬의 행을 의미한다 할 필요가 다음 사용하는 경우 내 통합 기능. 이 작업을 정확하게 수행하도록 설계되어 표시기 시리즈의 값에 따라 데이터를 줄입니다. (사실, 통합 자 또한 차 데이터에서 작동하고, 허용 오차,하지만 당신이해야 할 모든이에게 월 및 연도 정보를 전달하는 것입니다 수 있습니다.)

Find consolidator on the file exchange on Matlab Central