2015-12-29 3 views
5

私はこのようなデータを持っている:マトリックス内の値(稼働時間)が連続して出現する長さを計算するにはどうすればよいですか?

1  0  1 
1  1  1 
0  1  1 
1  1  1 
1  1  1 
1  1  1 
1  1  0 
1  1  1 
1  1  1 
1  1  1 
1  1  1 
1  1  1 
1  1  1 
1  1  1 
0  0  1 
1  1  1 
1  1  1 
1  1  1 

各列はデバイスを表し、各行は時間を表します。各データポイントは、その期間にデバイスがアクティブであったかどうかを示します。私は、それぞれのデバイスがアクティブであったという各稼働時間の長さ、すなわち「呪文」を計算しようとしています。言い換えれば、各列の連続する呪文の長さ。この場合、最初の列には2 11 3、以下同様です。

これは、1つのデバイス(データの単一の列)で行うことは容易である:

rng(1) 

%% Parameters 
lambda = 0.05;  % Pr(failure) 
N = 1;    % number of devices 
T = 18;    % number of time periods in sample 

%% Generate example data 
device_status = [rand(T, N) >= lambda ; false(1, N)]; 

%% Calculate spell lengths, i.e. duration of uptime for each device 
cumul_status = cumsum(device_status); 

% The 'cumul_status > 0' condition excludes the case where the vector begins with one 
% or more zeros 
cumul_uptimes = cumul_status(device_status == 0 & cumul_status > 0); 
uptimes = cumul_uptimes - [0 ; cumul_uptimes(1:end-1)]; 

ので、私は単に列を反復し、一度にこのつの列を行うと、parforを使用可能性(例えば)これを並行して実行する。ベクトル化された行列演算を使用して、これをすべての列で同時に実行する方法はありますか?

編集:これは、各デバイスに異なる数の習慣があるかもしれないという事実によって複雑になります。

+0

'reshape(max(cumsum(cumprod(hankel)[0(1、size(A、2)); A]) ')))、size(A、1)+ 1、size(A、2)); 'Aは行列です。次に、ローカルの最大値を見つけることができますが、ループを使用する方が時間がかかります。 – obchardon

+1

多くのデバイスをお持ちでない場合は、このアプローチをループで使用すると問題はないと思います。物事を過度に複雑化しないでください。ドナルド・クヌス氏は、「時期尚早最適化はすべての悪の根源である」と最高の言葉を述べました*。ベクトル化された方法ですべてのデバイスでこれを実行しようとするよりも、個々のデバイスのルーピング間に大きなランタイムの違いがはっきりと見られる場合を除き、それは価値がありません。 – rayryeng

+1

サイドローとしても、各列のアップタイムは同じになることはありません。具体例では、最初の列に3つの稼働時間インスタンスがあり、最後の2つには2つのインスタンスがあります。この「不均一性」は、すでにベクトル化の能力を妨げています。 – rayryeng

答えて

3

ここには方法があります。しかし、ベクトル化されているとは思わない。

データマトリックスをxと表記してください。次に、

[ii, jj] = find([true(1,size(x,2)); ~x; true(1,size(x,2))]); 
result = accumarray(jj, ii, [], @(x){nonzeros(diff(x)-1)}); 

は、各セルが列に対応するセル配列を生成します。これは

アイデアは(つまり、~xtrue値である)xにゼロの行と列のインデックスを見つけ、その後、列のインデックスを使用することですの仕組みあなたの例では、

result{1} = 
    2 
    11 
    3 
result{2} = 
    13 
    3 
result{3} = 
    6 
    11 

グループ化変数として(最初の引数はaccumarray)。

anonymous function@(x){nonzeros(diff(x)-1)}を使用して、0の行位置の違いを計算します。 Matlabのcolumn majorオーダーのおかげで、findの列インデックスが既にソートされているため、diffを直接適用することができます。 xの0は稼働時間の一部としてカウントされないため、1を減算します。 0nonzeros)と等しい稼働時間の長さを除去し、得られたベクターを細胞({...})に詰める。

trueの値の行が追加され、~xの先頭に追加され、初期および最終稼働時間が検出されるようにします。

関連する問題