使用矩阵而不是数据表时 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);