高效的移動平均算法<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 或更多),計算時間變得不合理。 有人有更快的移動平均線方法嗎?
謝謝!
丹麥人
回复:高效的移動平均算法我通常發現,如果我能一起避開桌子,速度會更快。 這在我的機器上運行得更快。 您會注意到 My numbers 也不同於 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);回复:高效的移動平均算法這是一個很好的解決方案。 請注意,數據列(本例中為“當前”)中的任何缺失值都會在計算數據列中從第一個缺失數據出現的行到下面的所有行創建空白值。 這是一個需要注意的小問題。回复:高效的移動平均算法謝謝,傑夫。 這些比求和法運行得快得多!
回复:高效的移動平均算法我可以在這裡提供一些策略。
我認為兩者都比您當前使用的 Summation() 運算符更有效。 我不能說它們是最有效的。
1) 在矩陣上使用 Sum() 函數。
If(Row()<:Moving Avg Window,
.,
Sum( :Current[Index( Row() - (:Moving Avg Window - 1), Row() )] ) / :Moving Avg Window
)

這利用了矩陣運算的速度。 的下標當前的此公式中的列是從移動平均窗口開始到當前行號的行號矩陣。 我以這種方式為列下標,JMP 返回一個矩陣,而 Sum 函數在矩陣上相對有效。
不過,一種更快的方法是計算兩列的移動平均值。 第一列簡單地通過添加值來維護移動總和當前的在一行中將前一行中的滾動總和的值減去,然後從窗口開頭的行中減去 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,
.
)

我附上了顯示這兩種方法的數據表。 在數據表中移動平均窗口是一個數據表變量.
要查看此數據表中第二種方法的效率,您可能需要打壓評價的的移動平均(x)專欄第一。
-傑夫