ロク逆関数こんにちは、みんな。特定のタスクのためにこのJSL関数を作成しましたが、これを行うためのより良い方法があるかどうか疑問に思っていました.
私が欲しいのは、インデックスのベクトルがある場合、ベクトル要素の値が指定されたインデックスの場合は 1 で、それ以外の場合は 0 である指定されたリンクの指標ベクトルを作成する方法です。例えば
[2, 3, 6] --> 長さ 10 の指標ベクトルに変換します。
[0, 1, 1, 0, 0, 0, 1, 0, 0, 0]
ユース ケースは、複数の条件に基づいてデータ テーブル内の行のサブセットを選択するためのものです。条件ごとに、条件を満たす行番号のベクトルを取得し、すべての条件を満たす行を取得したいと考えています。
// Loc Inverse Function
// This function converts a vector of positive integers (locvals) into an
// indicator vector of a specified length, n, with the values
// v[I] = 1 if I is in locvals, and 0 otherwise
// example
// Loc Inverse(6, [1,3])
// returns
// [1, 0, 1, 0, 0, 0]
*/
Loc Inverse = Function( {n, locvals},
v = J( n, 1, 0 );
v[locvals] = 1;
v;
);
したがって、ユースケースでは、たとえば、3 つの条件がある場合、各条件 (v1、v2、v3) を満たすベクトルで行番号を取得するので、これを行います。
dt=current data table();
Loc Inverse = Function( {n, locvals},
v = J( n, 1, 0 );
v[locvals] = 1;
v;
);
// ...
// code to get v1, v2, v3
// ...
rowindicator1=Loc Inverse(n rows(dt), v1);
rowindicator2=Loc Inverse(n rows(dt), v2);
rowindicator3=Loc Inverse(n rows(dt), v3);
meet_all_conditions_indicator = rowindicator1 & rowindicator2 & rowindicator3;
rows_that_meet_all_conditions = Loc(meet_all_conditions_indicator);Re: ロク逆関数あなたのアプローチはいいと思います。 多数の、または不明な数の句、および/または多数の行がある場合、行番号の行列のリストを受け入れるこの関数を試すことができます。
common = function({nr, vList},
{default local},
mat = J(nr, 1, 0);
for each( {i}, 1::nitems(vList), mat[vlist[i]]++ );
return(loc(mat, nitems(vList)))
);
ここでの主な利点は、フルサイズの配列を 1 つだけ作成して格納する必要があることです。 以下は、100 万行を超える 6 つの句の実行時間を比較する例です。
names default to here(1);
nr = 1e6;
p = 0.6;
nClause = 6;
//create a list of vectors, each representing the rows returned from a given clause.
//rows are selected with probability p within any clause
vecLis = {};
for each( {i}, 1::nClause, insertinto(vecLis, loc(J(nr,1, randombinomial(1,p)))));
Loc Inverse = Function( {n, locvals},
v = J( n, 1, 0 );
v[locvals] = 1;
v;
);
common = function({nr, vList},
{default local},
mat = J(nr, 1, 0);
for each( {i}, 1::nitems(vList), mat[vlist[i]]++ );
return(loc(mat, nitems(vList)))
);
t1 = hptime();
rws = common(nr,vecLis);
t2 = hptime();
t3 = hptime();
rowindicator1=Loc Inverse(nr, vecLis[1]);
rowindicator2=Loc Inverse(nr, vecLis[2]);
rowindicator3=Loc Inverse(nr, vecLis[3]);
rowindicator4=Loc Inverse(nr, vecLis[4]);
rowindicator5=Loc Inverse(nr, vecLis[5]);
rowindicator6=Loc Inverse(nr, vecLis[6]);
meet_all_conditions_indicator = rowindicator1 & rowindicator2 & rowindicator3 & rowindicator4 & rowindicator5 & rowindicator6;
rows_that_meet_all_conditions = Loc(meet_all_conditions_indicator);
t4 = hptime();
//Print(evalinsert("Number of Rows: ^nr^.\!NProportion 'Yes' ^p^.\!NNumber of clauses: ^nClause^."));
Print(evalinsert("single matrix approach: ^(t2-t1)/1e6^ secs."));
Print(evalinsert("InvLoc approach: ^(t4-t3)/1e6^ secs."));
Print(evalinsert("Answers differ or are empty: ^try(sum(rws != rows_that_meet_all_conditions), 1)"));

Re: ロク逆関数質問を誤解しているかもしれませんが、連想配列は 2 つの集合の交差集合を取得できます。
Names Default To Here(1);
/* Sample Data */
n = 30000;
p = 9;
vec = J(n, p, .);
For(i = 1, i <= NCol(vec), i++,
vec[0, i] = (1::n)`*i;
);
/* From Here */
a={};
For(i = 1, i<=NCol(vec), i++,
a[i] = Associative Array(vec[0,i]);
);
For(i = 2, i <= N Items(a), i++,
a[1] << Intersect(a[i]); /* Intersection Set (A1 cap A2 cap ... cap Ap)*/
);
answer = a[1] <<GET keys=""></GET>Re: ロク逆関数ゆうすけさん、こんにちは。
連想配列を議論に持ち込んでくれてありがとう。 あなたが言及したように、 <
例として、30K 行 x 9 列のサンプル データ セットを使用して各方法を比較するためのコードとログ出力を以下に示します。 この場合、連想配列メソッドは、マトリックス メソッドの実行に約 65 倍の時間がかかります。
乾杯、
ブレイディ
Names Default To Here( 1 );
/* Sample Data */
n = 30000;
p = 9;
vec = J( n, p, . );
For( i = 1, i <= N Col( vec ), i++,
vec[0, i] = (1 :: n)` * i
);
t1 = HP Time();
a = {};
For( i = 1, i <= N Col( vec ), i++,
a[i] = Associative Array( vec[0, i] )
);
For( i = 2, i <= N Items( a ), i++,
a[1] << Intersect( a[i] ); /* Intersection Set (A1 cap A2 cap ... cap Ap)*/
);
answer = a[1] << Get Keys;
t2 = HP Time();
common = Function( {nr, vList},
{default local},
mat = J( nr, 1, 0 );
For Each( {i}, 1 :: N Items( vList ), mat[vlist[i]]++ );
Return( Loc( mat, N Items( vList ) ) );
);
t3 = HP Time();
vecLis = {};
For Each( {i}, 1 :: N Col( vec ), Insert Into( vecLis, vec[0, i] ) );
nr = Max( vec );
answer2 = common( nr, vecLis );
t4 = HP Time();
Print( Eval Insert( "AAs: ^(t2-t1)/1e6^ secs; ^answer^." ) );
Print( Eval Insert( "matrix: ^(t4-t3)/1e6^ secs; ^answer2^." ) );

Re: ロク逆関数ブレイディさん、ありがとうございました
以下のように For Each も試してみましたが、マトリックス メソッドの方が高速です。 ベクトルから連想配列を作成するには、かなりの時間がかかると思います。
t1 = HP Time();
a = Associative Array(vec[0, 1]);
For Each({i}, 2::N Col(vec),
a << Intersect(Associative Array( vec[0, i] ));
);
answer = a << Get Keys;
t2 = HP Time();