Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datosTodo,
¿Existe una alternativa al lag() que pueda usar cuando trabajo con matrices en lugar de tablas de datos? Básicamente, me gustaría poder ver el valor de la fila anterior de mi columna en una matriz para determinar el valor de la fila actual. Esto se puede lograr fácilmente usando la función lag() en una tabla de datos. ¿Cuál es una forma eficaz, además del bucle, para lograr esto si se trabaja con matrices?
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: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datosAquí hay una variación de la solución de Vince con la que estaba jugando. Él podría o podría No captura los requisitos, pero podría explicar cómo realizar las manipulaciones que necesita.
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: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datosSeguro.Entonces, si miramos tu fórmula (aparte de la primera fila = 0)
If( Mod( Lag( :RandomList ), 2 ) == 0,
:RandomList[Row()] + 1,
:RandomList[Row()] - 1
)
Lo veo como 3 partes, el retraso, la comprobación mod == 0 del retraso y la expresión else de eso.
Entonces primero hago el retraso.
lv = lag_matrix(v, 1);
entonces obtengo el vector mod
mod_vector = lv / 2 - floor(lv/2);
pero me acabo de dar cuenta de que el mod funciona en vectores, así que podrías hacerlo
mod_vector = mod(lv, 2);
que es significativamente más rápido
entonces obtengo un vector booleano haciendo
mod_vector == 0 y loc() para encontrar las filas donde el mod(2) del lag(1) es 0
loc_vector = loc(mod_vector==0);
loc_vector son las filas que coinciden con su declaración if
Mod( Lag( :RandomList ), 2 ) == 0
luego, para obtener las filas de la declaración else, invierto la selección haciendo un vector de todos los 1 y estableciendo las filas loc_vector en 0 y haciendo un loc()
invert_vector = J(nrows(v), 1);
invert_vector[loc_vector] = 0;
invert_vector = loc(invert_vector);
entonces, si concatenó los dos vectores y los ordenó, debería ser solo 1::nrows()
después de eso simplemente configuro las filas para la expresión if en +1 y la expresión else en -1
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
y finalmente establezca la primera fila en 0
v[1] = 0;
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos@vince_faller ,
Gracias por la solución, ¿podría explicar el proceso de pensamiento y cómo funciona si no es mucho pedir?
Veo que estás usando la combinación de la función lag_matrix, la función mod y loc() pero no entiendo la lógica.
Agradecería mucho una comprensión de la lógica para poder aprender el proceso (de nuevo, sólo si no es mucho pedir).
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datosNo es exactamente muy fácil de usar, pero incluso todos estos pasos siguen siendo ~3 veces más rápidos (436:135 us) en mi computadora cuando ejecuto el vector frente a la columna.Definitivamente hay optimizaciones que puedes hacer para hacerlo más rápido también. Cuando lo puse en 1000 filas, fue ~4 veces más rápido (1057:227us). Además, al parecer se deshicieron de Apply, mi mala.
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>
Espero que esto ayude un poco.
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos@vince_faller ,
¿Pueden ayudarme a implementar lo siguiente en una matriz sin bucle?
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))));Además, no pude encontrar las funciones apply() o applyOver() en mi índice de secuencias de comandos. Estoy usando JMP 14. ¿Es cosa de JMP Pro?
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos¿Qué estás intentando hacer realmente?Tienes razón en que las matrices suelen ser más rápidas, pero recorrerlas (en mi experiencia) normalmente perderá cualquier beneficio.JMP 14 ahora tiene las funciones apply() y applyOver() pero no he tenido mucha suerte usándolas.
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos@XanGregg , @Craige_Hales
Xan o Craige: si es posible, les pediría que hicieran una publicación de blog que cubra en detalle cómo realizar la vectorización con numerosos ejemplos en JSL. Este tema se trata detalladamente en SAS, R, Matlab y otros entornos. Me encantaría ver algo similar para JMP. Si ya existe algo similar, le ruego que me lo comunique.
Blogs de SAS - https://blogs.sas.com/content/iml/2013/05/15/vectorize-computations.html
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos@gzmorgan0 ,
Lo que intento pedir es una forma de evitar el bucle y confiar en el código vectorizado. Es recomendable reemplazar los bucles con funciones matriciales para hacer el código más eficiente ( https://community.jmp.com/t5/JMP-Blog/JSL-Tip-Replace-Loops-with-Functions-on-Matrices/ba-p/29783 ). Esto se logra en R mediante las funciones familiares de aplicación y en Matlab mediante algunas funciones matriciales o funciones personalizadas. Estoy preguntando si hay una manera de implementar dicho código vectorizado en matrices en lugar de intentar escribir un bucle en este caso para encontrar el retraso ().
@gzmorgan0 escribió:
Hoy,
No sé lo que estás preguntando. Puedes simplemente hacer referencia a la fila j-1. El script muestra los resultados de lag1 y 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)
);
En el ejemplo que proporcionó, definitivamente entiendo que es fácil escribir un bucle y obtener el equivalente de lag(); sin embargo, a medida que aumenta el tamaño de sus conjuntos de datos o el número de iteraciones, esto ralentizará su código. Estoy buscando un reemplazo eficiente, es decir, un equivalente vectorizado de implementar operaciones repetitivas en matrices en JSL.
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datosHoy,
No sé lo que estás preguntando. Puedes simplemente hacer referencia a la fila j-1. El script muestra los resultados de lag1 y 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: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos@vince_faller ,
Gracias por la solución que ha ofrecido, ¿hay alguna manera de modificar esta función para obtener solo la fila anterior en lugar de toda la matriz?
Tal vez la pregunta apropiada sería cuál es el formato vectorizado para realizar un bucle alrededor de una matriz con la función, similar a aplicar funciones en R que son mucho más rápidas que los bucles.
Re: Alternativa a Lag() cuando se trabaja con matrices en lugar de tablas de datos¿Esto funciona para tí?
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);