Loc 反函数大家好。我为特定任务制作了此 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;
);
因此,对于用例,例如,如果我有三个条件,我会得到满足每个条件(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);回复:Loc 反函数我认为你的方法很好。 如果您有许多或未知数量的子句和/或许多行,您可以尝试使用此函数,它接受行号矩阵列表:
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)))
);
这里的主要好处是只需要创建和存储一个全尺寸数组。 下面是一个比较超过一百万行的 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)"));

回复:Loc 反函数虽然我可能会误解这个问题,Associative Array 可以得到两个集合的交集。
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>回复:Loc 反函数你好佑介先生,
感谢您将关联数组带入讨论。 正如您提到的,<
作为示例,下面我包含代码和日志输出,以使用 30K 行乘 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^." ) );

回复:Loc 反函数非常感谢,布雷迪桑
我也尝试 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();