効率的な移動平均アルゴリズム<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />こんにちは、
以前にここに投稿した人たちのおかげで、いくつかの有用な回答が見つかりました!
オシロスコープからの大きなデータ セット (それぞれ 2000 万ポイント!) がいくつかあります。 移動平均を計算したい。 しかし、私が考案したアルゴリズムは非常に遅いです。 これが私の式のコードです:
"
If(Row() < 100, Empty(), Summation(i = Row() - 99, Row(), :Current[i,Empty()]) / 100)
"

平均化ウィンドウの幅 (この場合は 100 サンプル) が大きくなると (たとえば 500、1000、または 50000 以上)、計算時間が不合理になります。 誰かが移動平均を行うより速い方法を持っていますか?
ありがとう!
デーン
Re: 効率的な移動平均アルゴリズム私は通常、テーブルをすべて一緒に回避できれば、より高速であることがわかります。 これは私のマシンでより速く実行されます。 私の番号も Jeffs の番号とは異なることに気付くでしょう。 これは単純に、最後に数字をミラーリングし、中心から x ポイント (最後の x ポイントではなく) 移動するためです。 また、これには欠損値の重み付けがあるため、欠損値があっても問題ありません。 少なくとも私はそう思う。 最後に列が必要ない場合は、さらに高速です。 そして、それは基本的に連結されたインデックス マトリックスであるため、非常に高速です。
Names Default to here(1);
dt = open("$SAMPLE_DATA\Big Class.jmp");
st1 = HPtime();
mat = :height << Get Values;
//number of rows you want to average
x= 5;
//+- gap
z = (x-1)/2;
//get the rows
rows = 1::nrows(mat);
//mirror the rows on the front and back
mirrored = ((z+1)::2)||rows||((ncol(rows)-1)::(ncol(rows)-z));
big_mat = [];
for(i=0, i<=x-1, i++,
//this is cutting up the longer mirrored vector into x vectors of the same length as the original
big_mat ||= mat[mirrored[rows+i]];
);
//now we can just take a VSum of the transpose /x to get our average
Squasher = !ismissing(big_mat); //everywhere there's a non-missing, make 1
Squasher = VSum(Squasher`); //count real numbers, this is to not weight non-missings
A = Vsum(big_mat`)/x;
New Column("Moving Average", Set Values(A)); //If you don't need this column
//and you're just doing matrix operations this is actually about half the total time
en1 = HPTime()-st1;
// Data Table method
st2 = HPTime();
dt<< New Column("moving sum(x)", formula(If(Row()<=:Moving Avg Window,
If( Row() == 1,
:height,
Lag( :Name( "moving sum(x)" ), 1 ) + :height
),
(Lag( :Name( "moving sum(x)" ), 1 ) + :height) -
Lag( :height, :Moving Avg Window )
)));
dt<< New Column("Moving Avg", Formula(
If(Row()>=:Moving Avg Window,
:Name( "moving sum(x)" ) / :Moving Avg Window,
.
)));
en2 = HPTime()-st2;
show(en1, en2);Re: 効率的な移動平均アルゴリズムそれは素晴らしい解決策です。 データ列 (この例では「現在」) に欠損値があると、最初の欠損データが発生した行からその下のすべての行まで、計算されたデータ列に空白の値が作成されることに注意してください。 知っておくべき小さな問題です。Re: 効率的な移動平均アルゴリズムありがとう、ジェフ。 これらは、合計法よりもはるかに高速に実行されます。
Re: 効率的な移動平均アルゴリズムここでいくつかの戦略を提供できます。
どちらも、現在使用している Summation() 演算子よりも効率的だと思います。 ただし、それらが可能な限り最も効率的であるとは言えません。
1) マトリックスで Sum() 関数を使用します。
If(Row()<:Moving Avg Window,
.,
Sum( :Current[Index( Row() - (:Moving Avg Window - 1), Row() )] ) / :Moving Avg Window
)

これは、行列演算の速度を利用します。 の添え字現在この数式の列は、移動平均ウィンドウの開始から現在の行番号までの行番号の行列です。 このように列に添字を付けると、JMP は行列を返し、Sum 関数は行列よりも比較的効率的です。
ただし、さらに高速な方法は、この移動平均を 2 つの列で計算することです。 最初の列は、次の値を加算することによって単純に移動合計を維持します。現在1 つの行で、前の行のローリング合計の値に加算し、ウィンドウの先頭の行から Current の値を減算します。
移動合計の式は次のとおりです。
If(Row()<=:Moving Avg Window,
If( Row() == 1,
:Current,
Lag( :Name( "moving sum(x)" ), 1 ) + :Current
),
(Lag( :Name( "moving sum(x)" ), 1 ) + :Current) -
Lag( :Current, :Moving Avg Window )
)

次に、分割する列を持つのは簡単です移動合計によって移動平均ウィンドウ.
If(Row()>=:Moving Avg Window,
:Name( "moving sum(x)" ) / :Moving Avg Window,
.
)

これらの方法の両方を示すデータ表を添付しています。 データ表では、移動平均ウィンドウですデータ テーブル変数.
このデータ テーブルで 2 番目の方法の効率を確認するには、評価を抑えるの移動平均(x)最初の列。
-ジェフ