6

更新:質問テキストの下部にある 3 つの回答の簡単な分析を提供し、私の選択を説明しました。

私の質問:古いデータを使用してランダムな間隔のデータセットから固定間隔のデータセットを構築する最も効率的な方法は何ですか?

いくつかの背景:上記は、統計における一般的な問題です。多くの場合、一連の観測がランダムな時間に発生します。それを呼び出しますInput。しかし、たとえば 5 分ごとに発生する一連の観測が必要です。それを呼び出しますOutput。このデータセットを構築する最も一般的な方法の 1 つは、古いデータを使用することです。つまり、各観測Output値を で最も最近発生した観測値と同じに設定しInputます。

そのため、サンプル データセットを構築するためのコードを次に示します。

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

どちらのデータセットも、千年紀の変わり目の真夜中近くに始まります。ただし、 のタイムスタンプはInputランダムな間隔で発生しますが、 のタイムスタンプはOutput一定の間隔で発生します。簡単にするために、 の最初の観測がInput常に の最初の観測の前に発生するようにしましたOutput。どの回答でも、この仮定を自由に行ってください。

現在、次のように問題を解決しています。

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

確かに、この問題を解決するためのより効率的な、または少なくともよりエレガントな方法はありますか? 前述したように、これは統計の一般的な問題です。おそらくMatlabには、私が気付いていない組み込み関数がありますか? いくつかの大規模なデータセットに対してこのルーチンをたくさん使用しているので、どんな助けでも大歓迎です。

答え:こんにちは、私は 3 つの答えを分析しました。

ChthonicDaemon の答えは、実装が明らかに最も簡単ですが、非常に遅いです。これは、オブジェクトへの変換がtimeseries速度テストの外で行われる場合でも当てはまります。現時点では、このresample関数には多くのオーバーヘッドがあると思います。私は 2011b を実行しているので、その間に Mathworks によって改善された可能性があります。また、このメソッドは、 のOutput後に複数の観測が終了する場合に備えて、追加の行が必要Inputです。

Rody の回答は、Angainor の回答よりもわずかに遅いだけですが (どちらもこのhistcアプローチを採用していることを考えると驚くことではありません)、いくつかの問題があるようです。まず、 の最後の観測を割り当てる方法は、 の最後の観測の後に発生するOutputの最後の観測に対してロバストではありません。これは簡単な修正です。しかし、Angainor によって採用されたのではなく、最初の入力として持っていることに起因すると思われる 2 番目の問題があります。サンプル入力を設定するときに に変更すると、問題が発生します。InputOutputInputTimeStamphistcOutputTimeStampOutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001)';OutputTimeStamp = 730486.002 + (0:0.0001:TOutput * 0.0001 - 0.0001)';

Angainor は、私が投げたすべてのものに対して堅牢であるように見え、さらに最速でした。

さまざまな入力仕様に対して多くの速度テストを行いました。次の数値はかなり代表的なものです。

私の素朴なループ:Elapsed time is 8.579535 seconds.

アンガノール:Elapsed time is 0.661756 seconds.

ロディ:Elapsed time is 0.913304 seconds.

ChthonicDaemon:Elapsed time is 22.916844 seconds.

Angainor のソリューションに +1 を付けて、質問に解決済みのマークを付けます。

4

2 に答える 2

2

この「古いデータ」アプローチは、信号および時系列フィールドのゼロ次ホールドとして知られています。これを検索すると、多くのソリューションがすぐに表示されます。Matlab 2012b を使用している場合、これはすべて関数timeseriesを使用してクラスに組み込まれているため、単純に実行します。resample

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
于 2012-10-03T08:38:50.853 に答える
1

ここに問題に対する私の見解があります。histc行く方法です:

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

いくつかの異なる入力モデルの手順を確認しました (出力タイムスタンプの数を変更しました)。結果は同じです。しかし、私はまだあなたの問題を理解できていないので、ここで何か問題がある場合はお知らせください。

于 2012-10-03T07:54:51.817 に答える