2012-10-03 6 views
6

Update: Ich habe eine kurze Analyse der drei Antworten am Ende des Fragetextes bereitgestellt und meine Auswahlmöglichkeiten erläutert.Erstellen von festen Intervalldatensätzen aus zufälligen Intervalldatensätzen mit veralteten Daten

Meine Frage: Was ist die effizienteste Methode zum Erstellen eines festen Intervalldatensatzes aus einem Zufallsintervall-Dataset mit veralteten Daten?

Einige Hintergrund: Das oben genannte ist ein häufiges Problem in der Statistik. Häufig hat man eine Folge von Beobachtungen zu zufälligen Zeiten. Nennen Sie es Input. Aber man möchte eine Folge von Beobachtungen, etwa alle 5 Minuten. Nennen Sie es Output. Eine der gebräuchlichsten Methoden zum Erstellen dieses Datensatzes besteht darin, veraltete Daten zu verwenden, d. H. Jede Beobachtung in Output gleich der zuletzt aufgetretenen Beobachtung in Input einzustellen.

So, hier ist einige Code-Beispiel-Datensätze zu erstellen:

TInput = 100; 
TOutput = 50; 

InputTimeStamp = 730486 + cumsum(0.001 * rand(TInput, 1)); 
Input = [InputTimeStamp, randn(TInput, 1)]; 

OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001)'; 
Output = [OutputTimeStamp, NaN(TOutput, 1)]; 

Beide Datensätze an der Jahrtausendwende in der Nähe von Mitternacht beginnen. Die Zeitstempel in Input treten jedoch in zufälligen Intervallen auf, während die Zeitstempel in Output in festen Intervallen auftreten. Der Einfachheit halber habe ich dafür gesorgt, dass die erste Beobachtung in Input immer vor der ersten Beobachtung in Output erfolgt. Fühlen Sie sich frei, diese Annahme in irgendwelchen Antworten zu machen.

Derzeit löse ich das Problem wie folgt aus:

sMax = size(Output, 1); 
tMax = size(Input, 1); 
s = 1; 
t = 2; 
%#Loop over input data 
while t <= tMax 
    if Input(t, 1) > Output(s, 1) 
     %#If current obs in Input occurs after current obs in output then set current obs in output equal to previous obs in input 
     Output(s, 2:end) = Input(t-1, 2:end); 
     s = s + 1; 
     %#Check if we've filled out all observations in output 
     if s > sMax 
      break 
     end 
     %#This step is necessary in case we need to use the same input observation twice in a row 
     t = t - 1; 
    end 
    t = t + 1; 
    if t > tMax 
     %#If all remaining observations in output occur after last observation in input, then use last obs in input for all remaining obs in output 
     Output(s:end, 2:end) = Input(end, 2:end); 
     break 
    end 
end 

Sicherlich gibt es eine effizientere, oder zumindest, eleganter Weg, um dieses Problem zu lösen? Wie ich bereits erwähnte, ist dies ein häufiges Problem in der Statistik. Vielleicht hat Matlab eine eingebaute Funktion, die mir nicht bekannt ist? Jede Hilfe würde sehr geschätzt werden, da ich diese Routine eine Menge für einige große Datensätze verwende.

DIE ANTWORTEN: Hallo zusammen, ich habe die drei Antworten analysiert, und wie sie sind, ist Angainor das Beste.

Die Antwort von ChthonicDaemon ist zwar am einfachsten zu implementieren, aber sehr langsam. Dies gilt auch dann, wenn die Konvertierung in ein Objekt timeseries außerhalb des Geschwindigkeitstests erfolgt. Ich schätze, die resample Funktion hat im Moment eine Menge Overhead. Ich laufe 2011b, also ist es möglich, dass Mathworks es in der Zwischenzeit verbessert hat. Außerdem benötigt diese Methode eine zusätzliche Zeile für den Fall, dass Output mehr als eine Beobachtung nach Input beendet.

Die Antwort von Rody läuft nur etwas langsamer als die von Angaindor (nicht überraschend, da beide den histc Ansatz verwenden), scheint jedoch einige Probleme zu haben. Erstens ist das Verfahren zum Zuweisen der letzten Beobachtung in Output nicht robust gegenüber der letzten Beobachtung in Input, die nach der letzten Beobachtung in Output auftritt. Dies ist eine einfache Lösung. Aber es gibt ein zweites Problem, von dem ich denke, dass es InputTimeStamp als die erste Eingabe zu histc statt der OutputTimeStamp, die von Angainor angenommen wird, hat. Das Problem tritt auf, wenn Sie beim Einrichten der Beispieleingänge OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001)'; in OutputTimeStamp = 730486.002 + (0:0.0001:TOutput * 0.0001 - 0.0001)'; ändern.

Angainor scheint robust zu allem, was ich warf, und es war der schnellste.

ich viel Speed-Tests für verschiedene Eingangsspezifikationen haben - die folgenden Zahlen sind ziemlich repräsentativ:

Meine naive Schleife: Elapsed time is 8.579535 seconds.

Angainor: Elapsed time is 0.661756 seconds.

Rody: Elapsed time is 0.913304 seconds.

ChthonicDaemon: Elapsed time is 22.916844 seconds.

Ich bin + 1-Ing Angainor Lösung und markiert die Frage gelöst.

+0

Nur klar zu sein: es ist wichtig, dass die Zeiten nicht in Ordnung sind? In den meisten Fällen werden Beobachtungen in streng aufsteigender Zeit gemacht. – chthonicdaemon

+0

@chtonicdaemon Sie können davon ausgehen, dass die Zeiten in aufsteigender Reihenfolge sind. Ich habe anscheinend sowohl die "Zeitreihen" -Klasse als auch die "Resample" -Funktion in 2011b, daher sollte ich in der Lage sein, Ihre Antwort zu testen. Prost. –

Antwort

1

Hier ist meine Sicht auf das Problem. histc ist der Weg zu gehen:

% find Output timestamps in Input bins 
N = histc(Output(:,1), Input(:,1)); 

% find counts in the non-empty bins 
counts = N(find(N)); 

% find Input signal value associated with every bin 
val = Input(find(N),2); 

% now, replicate every entry entry in val 
% as many times as specified in counts 
index = zeros(1,sum(counts)); 
index(cumsum([1 counts(1:end-1)'])) = 1; 
index = cumsum(index); 
val_rep = val(index) 

% finish the signal with last entry from Input, as needed 
val_rep(end+1:size(Output,1)) = Input(end,2); 

% done 
Output(:,2) = val_rep; 

ich gegen Ihre Verfahren für ein paar verschiedene Eingabemodelle geprüft (I die Anzahl der Ausgabezeitstempel geändert), und die Ergebnisse sind die gleichen. Ich bin mir jedoch immer noch nicht sicher, ob ich Ihr Problem verstanden habe. Wenn also etwas nicht stimmt, lassen Sie es mich wissen.

+0

Ich habe meine Auswahl erklärt und eine kurze Analyse aller 3 Antworten am Ende des Fragetextes hinzugefügt. Nochmals vielen Dank für Ihre Antworten. –

2

Dieser "veraltete Daten" -Ansatz ist in Signal- und Zeitreihenfeldern als zero order hold bekannt. Dies schnell zu suchen bringt viele Lösungen. Wenn Sie Matlab 2012b haben, ist dies alles in die timeseries Klasse gebaut unter Verwendung der resample Funktion, so würde man einfach tun

TInput = 100; 
TOutput = 50; 

InputTimeStamp = 730486 + cumsum(0.001 * rand(TInput, 1)); 
InputData = randn(TInput, 1); 
InputTimeSeries = timeseries(InputData, InputTimeStamp); 

OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001); 
OutputTimeSeries = resample(InputTimeSeries, OutputTimeStamp, 'zoh'); % zoh stands for zero order hold 
+0

Danke für die Antwort. Ich denke nicht, dass die "Sortierung" notwendig ist, da die Ausgabe von "rand" streng positiv ist, also sollte eine kumulative Summe darüber monoton steigend sein, ja? –

+0

Ich habe meine Auswahl erklärt und eine kurze Analyse aller 3 Antworten am Ende des Fragetextes hinzugefügt. Nochmals vielen Dank für Ihre Antworten. –

+0

Ich habe den Cumsum Teil verpasst, danke. Ich bin ein wenig überrascht, dass das integrierte Resample so langsam ist, aber ich denke, es ist in Matlab eine Menge, der allgemeine Ansatz prüft die Robustheit, etc. – chthonicdaemon

Verwandte Themen