使用矩陣而非資料表時 Lag() 的替代方法全部,
在使用矩陣而不是資料表時,是否可以使用 lag() 的替代方案? 本質上,我希望能夠查看矩陣中列的前一行的值來確定當前行的值。 使用資料表中的 lag() 函數可以輕鬆實現這一點。 如果使用矩陣,除了循環之外還有什麼有效的方法來實現這一點?
dt = New Table("Test");
dt << New Column("Random-1",Numeric,Continuous,<< set values(Random Index(10^3,10^2)));
dt << New Column("AltToLag",Numeric,Continuous,Formula(If(Row()==1,0,Lag(:Name("Random-1")))));回覆:使用矩陣而非資料表時 Lag() 的替代方法這是我正在使用的文斯解決方案的變體。 它可能或者可能不捕獲需求,但可能會解釋如何進行您需要的操作。
R = [4, 6, 6, 5, 8, 7];
lag = 1;
// describe the adjustment
modamount = [1, -1];
// lagged values dont need the last value
lagged = R[1 :: N Rows( R ) - lag];// [4, 6, 6, 5, 8]
// adjustment is based on lagged values. add 1 for indexing.
adjust = modamount[1 + Mod( lagged, 2 )];// [1, 1, 1, -1, 1]
// source data does not need the first value
source = R[1 + lag :: N Rows( R )]; // [6, 6, 5, 8, 7]
// combine the adjustment with the source
combine = adjust + source; // [7, 7, 6, 7, 8]
// prepend a zero
answer = 0 |/ combine; // [0, 7, 7, 6, 7, 8]
回覆:使用矩陣而非資料表時 Lag() 的替代方法當然。因此,如果我們查看您的公式(第一行 = 0 除外)
If( Mod( Lag( :RandomList ), 2 ) == 0,
:RandomList[Row()] + 1,
:RandomList[Row()] - 1
)
我將其視為 3 個部分,即滯後、滯後的 mod == 0 檢查以及其 else 表達式。
所以我先做滯後
lv = lag_matrix(v, 1);
然後我得到 mod 向量
mod_vector = lv / 2 - floor(lv/2);
但我剛剛意識到 mod 適用於向量,所以你可以這樣做
mod_vector = mod(lv, 2);
這明顯更快
然後我得到一個布林向量
mod_vector == 0 和 loc() 找出 lag(1) 的 mod(2) 為 0 的行
loc_vector = loc(mod_vector==0);
loc_vector 是與 if 語句相符的行
Mod( Lag( :RandomList ), 2 ) == 0
然後為了取得 else 語句行,我透過建立全 1 的向量並將 loc_vector 行設為 0 並執行 loc() 來反轉選擇
invert_vector = J(nrows(v), 1);
invert_vector[loc_vector] = 0;
invert_vector = loc(invert_vector);
所以如果你連接兩個向量並排序,它應該只是 1::nrows()
之後,我只需將 if 表達式的行設為 +1,將 else 表達式設為 -1
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
最後將第一行設定為0
v[1] = 0;
回覆:使用矩陣而非資料表時 Lag() 的替代方法@vince_faller ,
感謝您提供解決方案,如果要求不過分,您能否解釋一下思考過程以及它是如何運作的。
我看到你正在使用 lag_matrix 函數、mod 函數和 loc() 的組合,但我不太明白其中的邏輯。
非常感謝邏輯的擴展,這樣我就可以學習思考過程(同樣,前提是要求不是太多)
回覆:使用矩陣而非資料表時 Lag() 的替代方法這並不完全是超級用戶友好的,但即使所有這些步驟在我的電腦上運行向量與列時仍然快了約 3 倍(436:135 us)。您肯定可以對此進行最佳化以使其更快。 當我將其設為 1000 行時,速度提高了約 4 倍(1057:227us)。 而且,顯然他們擺脫了Apply,我的錯。
dt = New Table( "Test" );
dt << New Column( "RandomList", Numeric, Continuous, <<SET values=""> 0,
lag_vector = lag_vector[1 :: n - Abs( lag )];
new_mat = empty_mat |/ mat[lag_vector, 0];
, //else
lag_vector = lag_vector[Abs( lag ) + 1 :: n];
new_mat = mat[lag_vector, 0] |/ empty_mat;
);
new_mat;
);
v = Column( dt, "RandomList" ) << Get Values;
check_vector = Column(dt, "DesFunc") << Get Values;
time_vector = HPTime();
//lag the vector
lv = lag_matrix(v, 1);
//mod the vector
mod_vector = lv / 2 - floor(lv/2);
//find the mods you want
loc_vector = loc(mod_vector==0);
//invert to find the mods you don't want
invert_vector = J(nrows(v), 1);
invert_vector[loc_vector] = 0;
invert_vector = loc(invert_vector);
//assign values
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
//set first row to 0
v[1] = 0;
time_vector = HPTime()-time_vector;
show(all(v == check_vector));
show(time_column, time_vector);
</SET>
希望這有幫助。
回覆:使用矩陣而非資料表時 Lag() 的替代方法@vince_faller ,
你能幫我在沒有迴圈的矩陣中實現以下內容嗎?
dt = New Table("Test");
dt << New Column("RandomList",Numeric,Continuous,<< Set Values(Random Index(10^3,10^2)))
<< New Column("DesFunc",Numeric,Continuous,Formula(If(Row() == 1,0,If(Mod(Lag(:RandomList),2)==0,:RandomList[Row()]+1,:RandomList[Row()]-1))));另外,我在腳本索引中找不到 apply() 或 applyOver() 函數。 我正在使用 JMP 14 。 這是 JMP Pro 的事情嗎?
回覆:使用矩陣而非資料表時 Lag() 的替代方法你到底想做什麼?你是對的,矩陣通常更快,但循環遍歷它們(根據我的經驗)通常會失去任何好處。JMP 14 現在有 apply() 和 applyOver() 函數,但我使用它們的運氣並不好。
回覆:使用矩陣而非資料表時 Lag() 的替代方法@XanGregg , @Craige_Hales
Xan 或 Craige - 如果可能的話,我實際上會請您發表一篇部落格文章,詳細介紹如何透過 JSL 中的大量範例執行向量化。 該主題在 SAS、R、Matlab 和其他環境中都有詳細介紹。 我希望 JMP 能看到類似的東西。 如果類似的東西已經存在,請您提請我注意。
SAS 部落格 - https://blogs.sas.com/content/iml/2013/05/15/vectorize-computations.html
回覆:使用矩陣而非資料表時 Lag() 的替代方法@gzmorgan0 ,
我試圖要求的是一種避免循環並依賴向量化程式碼的方法。 建議用矩陣函數替換循環以使程式碼更有效率( https://community.jmp.com/t5/JMP-Blog/JSL-Tip-Replace-Loops-with-Functions-on-Matrices/ba-p/29783 )。 這在 R 中透過 apply 系列函數實現,在 Matlab 中透過一些矩陣函數或自訂函數實現。 我請求是否有一種方法可以在矩陣上實現這樣的向量化程式碼,而不是在這種情況下嘗試編寫一個循環來尋找 lag()。
@gzmorgan0寫道:
烏代,
我不知道你在問什麼。 您可以只引用第 j-1 行。 該腳本顯示 lag1 和 diff1 結果。
Names Default to Here(1);
dt = Open("$sample_data/Big Class.jmp");
bcmat = dt << get as matrix; //Matrix(40,3)
for(j=2, j<=nrow(dt), j++,
lag1 = bcmat[j-1,0];
dif1 = bcmat[j,0] - bcmat[j-1,0];
show( lag1, dif1)
);
在您提供的範例中,我絕對理解編寫循環並獲得 lag() 等效項很容易,但是隨著資料集大小或迭代次數的增加,這會減慢您的程式碼速度。 我正在尋找一種有效的替代方案,即在 JSL 中對矩陣實現重複操作的向量化等效項。
回覆:使用矩陣而非資料表時 Lag() 的替代方法烏代,
我不知道你在問什麼。 您可以只引用第 j-1 行。 該腳本顯示 lag1 和 diff1 結果。
Names Default to Here(1);
dt = Open("$sample_data/Big Class.jmp");
bcmat = dt << get as matrix; //Matrix(40,3)
for(j=2, j<=nrow(dt), j++,
lag1 = bcmat[j-1,0];
dif1 = bcmat[j,0] - bcmat[j-1,0];
show( lag1, dif1)
);回覆:使用矩陣而非資料表時 Lag() 的替代方法@vince_faller ,
感謝您提供的解決方案,有沒有辦法修改此函數以僅獲取前一行而不是整個矩陣?
也許適當的問題是使用函數循環矩陣的向量化格式是什麼 - 類似於 R 中的應用函數,它比循環快得多。
回覆:使用矩陣而非資料表時 Lag() 的替代方法這對你有用嗎?
names default to here(1);
lag_matrix = function({mat, lag}, {DEFAULT LOCAL},
n = nrows(mat);
lag_vector = 1::n;
empty_mat = J(abs(lag), ncols(mat), .);
if(lag>0,
lag_vector = lag_vector[1::n-abs(lag)];
new_mat = empty_mat|/mat[lag_vector, 0];
, //else
lag_vector = lag_vector[abs(lag)+1::n];
new_mat = mat[lag_vector, 0]|/empty_mat;
);
new_mat;
);
lag_matrix((14::28)`||(28::42)`, -1);