データテーブルの代わりに行列を操作する場合の 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")))));Re: データテーブルではなく行列を扱う場合の Lag() の代替案これは、私が試した Vince のソリューションのバリエーションです。 それかもしれないまたはかもしれない要件を把握しているわけではありませんが、必要な操作を行う方法については説明しているかもしれません。
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]
Re: データテーブルではなく行列を扱う場合の Lag() の代替案もちろん。したがって、式を見ると(最初の行 = 0 以外)
If( Mod( Lag( :RandomList ), 2 ) == 0,
:RandomList[Row()] + 1,
:RandomList[Row()] - 1
)
私はこれをラグ、ラグの mod == 0 チェック、そしてその else 式の 3 つの部分として捉えています。
だから最初にラグを作ります
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);
したがって、2 つのベクトルを結合してソートすると、それは 1::nrows() になるはずです。
その後、if 式の行を +1 に設定し、else 式の行を -1 に設定します。
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
最後に最初の行を 0 に設定します
v[1] = 0;
Re: データテーブルではなく行列を扱う場合の Lag() の代替案@vince_faller 、
解決策をありがとうございます。質問しすぎなければ、思考プロセスとそれがどのように機能するかを親切に説明していただけますか。
lag_matrix 関数、mod 関数、loc() を組み合わせて使用しているようですが、ロジックがよくわかりません。
プロセスを学ぶことができるように、ロジックの概要を非常に感謝します(これも質問しすぎない場合に限ります)
Re: データテーブルではなく行列を扱う場合の 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>
これが少しでも役立つことを願っています。
Re: データテーブルではなく行列を扱う場合の 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() 関数が見つかりませんでした。 JMP14を使用しています。 それはJMP Proのものですか?
Re: データテーブルではなく行列を扱う場合の Lag() の代替案実際に何をしようとしているのでしょうか?行列の方が通常は高速であるということは正しいですが、行列をループすると (私の経験では) 通常、利点が失われます。JMP 14 には apply() 関数と applyOver() 関数が追加されましたが、私はそれらをうまく使用できませんでした。
Re: データテーブルではなく行列を扱う場合の Lag() の代替案@XanGregg 、 @Craige_Hales
Xan または Craige さん、もし可能であれば、JSL での多数の例を使用してベクトル化を実行する方法を詳細に説明するブログ投稿を作成していただけるようお願いいたします。 このトピックは、 SAS 、 R 、 Matlab およびその他の環境で詳しく説明されています。 JMP でも同様のものが見たいです。 同様のものがすでに存在する場合は、注意を払っていただくようお願いします。
SAS ブログ - https://blogs.sas.com/content/iml/2013/05/15/vectorize-computations.html
Re: データテーブルではなく行列を扱う場合の Lag() の代替案@gzmorgan0 、
私が求めようとしているのは、ループを回避し、ベクトル化されたコードに依存する方法です。 コードをより効率的にするために、ループを行列関数に置き換えることをお勧めします ( https://community.jmp.com/t5/JMP-Blog/JSL-Tip-Replace-Loops-with-Functions-on-Matrices/ba-p/29783 )。 これは、R では apply family 関数を通じて、Matlab ではいくつかの行列関数またはカスタム関数を通じて実現されます。 この場合、lag() を見つけるためにループを作成してみるのではなく、行列にそのようなベクトル化されたコードを実装する方法があるかどうかをリクエストしています。
@gzmorgan0書きました:
ウダイ、
何を聞いているのか分かりません。 行 j-1 を参照するだけです。 スクリプトは、lag1 と dif1 の両方の結果を表示します。
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で行列に対する反復操作を実装するのと同等のベクトル化されたものを探しています。
Re: データテーブルではなく行列を扱う場合の Lag() の代替案ウダイ、
何を聞いているのか分かりません。 行 j-1 を参照するだけです。 スクリプトは、lag1 と dif1 の両方の結果を表示します。
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)
);Re: データテーブルではなく行列を扱う場合の Lag() の代替案@vince_faller 、
提供した解決策をありがとうございます。行列全体ではなく前の行だけを取得するようにこの関数を変更する方法はありますか?
おそらく、適切な質問は、関数を使用して行列をループするベクトル化された形式は何なのかということでしょう。これは、ループよりもはるかに高速な R の関数の適用に似ています。
Re: データテーブルではなく行列を扱う場合の 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);