2014-03-03 2 views
1

안녕하세요 여러분, 새로운 작은 문제가 있습니다. 사용중인 데이터의 하루가 17:00에서 그 다음날 16.15로 바뀌는 이상한 거래 시간이 있습니다.데이터 소스의 오류 : for 루프가없는 벡터를 반복해서 수정 하시겠습니까?

DATE , TIME , PRICE 
09/27/2013,17:19:42,3225.00,1 #%first obs of the vector 
09/27/2013,18:37:59,3225.00,1 #%second obs of the vector 
09/27/2013,08:31:32,3200.00,1 
09/27/2013,08:36:17,3203.00,1 
09/27/2013,09:21:34,3210.50,1 #%fifth obs of the vector 

지금 제 1 및 제 2 OBS 나를 위해 잘못된 : 예를 들어, 일 2013년 9월 27일 소스에 대해 내가 거래로 발생 레지스터를 사용하고하는 것은 다음 것을 의미 그들은 9/27에 속하는 거래 일이지만 9/26에 처형되었습니다. 비 감소시기에 의존하는 MATLAB의 일부 기능을 연구하고 있기 때문에이 문제를 해결해야합니다. 내가 사용하고 날짜 형식은 실제로 난 그냥 잘못된 관찰에서 하나를 뺀 문제를 해결하기 위해 노력하고 있으므로 datenum matlab에 형식입니다 :

%#Call time the time vector, I can identify the 'incorrect' observations 
idx=find(diff(time)<0); 
time(idx)=time(idx)-1; 

단지 '마지막'잘못된를 해결할 것이라고 말할 쉽다 시리즈의 관찰. 앞의 예에서 두 번째 요소 만 수정합니다. idx가 비워 질 때까지 코드를 여러 번 실행해야합니다 (while 루프에 대해 생각했습니다). 작은 시리즈로 작업 할 때 큰 문제는 아니지만 최대 20 백만 건의 관측과 수십만 개의 연속 된 잘못된 관측이 있습니다.
이 문제를 벡터화 된 방법으로 해결할 수 있습니까?

idx=find(diff(time)<0); 
while idx 

그러나 계산은 내가 for 루프 효율적으로 문제를 해결할 수 있고 내 생각은 다음과 같은 것을 생각 그렇게 복잡하지 않을 것이라고 주어진 :

[N]=size(time,1); 
for i=N:-1:1 
    if diff(time(i,:)<0) 
    time(i,:)=time(i,:)-1; 
    end 
end 

슬프게도이 작동하는 것 같다하지 않습니다 .
다음은 실제로 사용하는 데이터의 예입니다.

735504.591157407 
735507.708030093  %# I made this up to give you an example of two consecutively wrong observations 
735507.708564815  %# This is an incorrect observation 
735507.160138889 
735507.185358796 
735507.356562500 

미리 감사드립니다 모두

답변

1

현명한 버전 -

for count = 1:numel(time) 
    dtime = diff([0 ;time]); 
    ind1 = find(dtime<0,1,'last')-1; 
    time(ind1) = time(ind1)-1; 
end 

빠른-하지만-미쳤 버전 -

dtime = diff([0 ;time]); 
for count = 1:numel(time) 
    ind1 = find(dtime<0,1,'last')-1; 
    time(ind1) = time(ind1)-1; 
    dtime(ind1+1) = 0; 
    dtime(ind1) = dtime(ind1)-1; 
end 

더 미쳤 버전 -

dtime = diff([0 ;time]); 
ind1 = numel(dtime); 
for count = 1:numel(time) 
    ind1 = find(dtime(1:ind1)<0,1,'last')-1; 
    time(ind1) = time(ind1)-1; 
    dtime(ind1) = dtime(ind1)-1; 
end 
다양한 datasizes 이러한 버전

일부 평균 계산 런타임 -

Datasize 1: 3432 elements 
Version 1 - 0.069 sec 
Version 2 - 0.042 sec 
Version 3 - 0.034 sec 

Datasize 2: 20 Million elements 
Version 1 - 37029 sec 
Version 2 - 23303 sec 
Version 3 - 20040 sec 
+0

고마워요, 부끄러움으로 작용했습니다. 방금 20M 관측 시리즈에서 실행했습니다. – Gio

+0

Kool! 3 가지 버전의 런타임에 크게 관심이 있습니다. 그들에게 tic-toc 런타임을 게시 할 수 있습니까? 3 가지 모두가 아니라면, 적어도 마지막 두 가지 버전이 있습니까? – Divakar

+0

나는 오늘 밤이 세 곡을 반복하여 내일 결과를 줄 수 있습니다. 어쨌든, 정말 좋은 답변, 축하해! – Gio

0

그래서 분명히 내가 루틴 Divakar 제안 stucked 수 있었다 생각 데이터 소스에서 다른 3 가지 문제가 있었다. 어쨌든 나는 그것이 너무 느려서 다른 해결책을 생각하기 시작했고 매우 빠른 벡터화 된 것을 생각해 냈습니다.

수정하려는 관측치가 일정한 알려진 시간 간격으로 떨어지는 것을 감안할 때 함수는 해당 간격에 속하는 모든 관측치를 찾고 원하는대로 수정합니다 (제 경우에는 -1 개).

function [ datetime ] = correct_date(datetime,starttime, endtime) 
%#datetime is my vector of dates and times in matlab numerical format 
%#starttime is the starting hour of the interval expressed in datestr format. e.g. '17:00:00' 
%#endtime is the ending hour of the interval expressed in datestr format. e.g. '23:59:59' 

if (nargin < 1) || (nargin > 3), 
    error('Requires 1 to 3 input arguments.') 
end 
% default values 
if nargin == 1, 
    starttime='17:00'; 
    endtime='23:59:59'; 
elseif nargin == 2, 
    endtime='23:59:59'; 
end 

tvec=[datenum(starttime) datenum(endtime)]; 
tvec=tvec-floor(tvec); %#As I am working on multiples days I need to isolate only HH:MM:SS for my interval limits 
temp=datetime-floor(datetime);   %#same motivation as in the previous line 
idx=find(temp>=tvec(1)&temp<=tvec(2)); %#logical find the indices 
datetime(idx)=datetime(idx)-1;   %#modify them as I want 
clear tvec temp idx 
end 
관련 문제