Loop that I am trying to get rid off

To follow up on my previous thread regarding a very time consuming routine, the main source of slowness I believe is the following: Rating agencies such as Moody and Standard and Poors report ratings for bonds outstanding. This rating changes from time to time. So I have in a matrix X0: column 1 is a bond ID Column 2 is the rating beginning date Column 3 is the rating Column 4 is the rating ending date for example for Bond ID 1 I have the following inputs: Ratings=[1 726834 3 728000;1 728000 2 729500;1 729500 3 731000]; then I have a vector date of 20 year daily data so I am running a loop that looks like this for a single bond (I have 15000 bonds):
for i=1:length(date)
x1=find(X0(:,2)<=date(i) & X0(:,4)>date(i));
if isempty(x1)
R(i)=nan;%Rating
else R(i)=X0(x1,3);
end
end
Is there a way to get rid of this loop ?

 채택된 답변

Oleg Komarov
Oleg Komarov 2011년 8월 6일

0 개 추천

% Preallocate R already with NaNs
R = NaN(size(date));
% Now we want to test how many dates belong to each rating period, to do this construct the edges of each period
edges = unique(X0(:,[2,4]));
% Total length or rating history (excluded last day of last period)
idx = date >= edges(1) & date < edges(end);
% Count ho many dates fall per period (last bucket is last day of last rating period, which is excluded)
len = histc(date, edges);
% Use run-length decoding (vectirized)
R(idx) = rude(len(1:end-1), X0(:,3));
Rude on FEX: here

댓글 수: 3

joseph Frank
joseph Frank 2011년 8월 6일
it is working wonderfully but for one observation I received an error
len=[676
438
69
62
447
192
454
3659
0];
X0=12739 726313 5 727261
12739 727261 6 727873
12739 727873 6 727970
12739 727970 7 728056
12739 728056 7 728683
12739 728683 7 728951
12739 728951 8 728951
12739 728951 8 729587
12739 729587 8 734710]
edges=726313
727261
727873
727970
728056
728683
728951
729587
734710];
I am receiving
??? Error using ==> rude>rl_decode at 74
rl-decoder: length mismatch
len = 8
val = 9
Error in ==> rude at 60
p1=rl_decode(varargin{1:2});
Error in ==> findrating at 28
R(idx) = rude(len(1:end-1), X0(:,3));
Oleg Komarov
Oleg Komarov 2011년 8월 6일
Look at X0:
12739 728951 8 728951
joseph Frank
joseph Frank 2011년 8월 6일
thanks. I eliminated the duplication

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Fangjun Jiang
Fangjun Jiang 2011년 8월 6일

1 개 추천

I wonder if you can use interp1(). Basically, it is a look up operation, right? It will fill NaNs for dates outside of Ratings. But there should be no gap of dates in Ratings.
Use your own discretion. BTW, don't use 'date' as the variable name. It's a function.
Ratings=[1 726834 3 728000;1 728000 2 729500;1 729500 3 731000];
X=[Ratings(:,2),Ratings(:,4)-1]';
X=X(:);
Y=[Ratings(:,3),Ratings(:,3)]';
Y=Y(:);
Dates=726830:731005;
R=interp1(X,Y,Dates,'nearest');
Daniel Shub
Daniel Shub 2011년 8월 6일

0 개 추천

Loops in MATLAB are much faster nowadays then they used to be. Without timing solutions, it is not always obvious what way is fastest. Sometimes you just want to get to fast enough.
It looks to me like you could loop over the rows of X0 instead of the dates.

카테고리

도움말 센터File Exchange에서 Characters and Strings에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by