Alternativa a Lag() quando si lavora con matrici invece che con tabelle di datiTutto,
Esiste un'alternativa a lag() che potrei utilizzare quando lavoro con matrici anziché con tabelle di dati? Essenzialmente, vorrei poter guardare il valore della riga precedente della mia colonna in una matrice per determinare il valore della riga corrente. Ciò può essere facilmente ottenuto utilizzando la funzione lag() in una tabella di dati. Qual è un modo efficace diverso dal looping per raggiungere questo obiettivo se si lavora con le matrici?
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")))));Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiEcco una variazione della soluzione di Vince con cui stavo giocando. Potrebbe o meno catturare i requisiti, ma potrebbe spiegare come eseguire le manipolazioni necessarie.
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]
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiSicuro. Quindi se guardiamo la tua formula (diversa dalla prima riga = 0)
If( Mod( Lag( :RandomList ), 2 ) == 0,
:RandomList[Row()] + 1,
:RandomList[Row()] - 1
)
Lo vedo come 3 parti, il ritardo, il controllo mod == 0 del ritardo e l'altra espressione di quello.
Quindi prima faccio il lag
lv = lag_matrix(v, 1);
quindi ottengo il vettore mod
mod_vector = lv / 2 - floor(lv/2);
ma ho appena realizzato che la mod funziona sui vettori, quindi potresti farlo
mod_vector = mod(lv, 2);
che è significativamente più veloce
quindi ottengo un vettore booleano facendo
mod_vettore == 0 e loc() per trovare le righe in cui mod(2) del lag(1) è 0
loc_vector = loc(mod_vector==0);
loc_vettore sono le righe che corrispondono alla tua istruzione if
Mod( Lag( :RandomList ), 2 ) == 0
quindi per ottenere le righe dell'istruzione else, inverto la selezione creando un vettore di tutti gli 1 e impostando le righe loc_ctor su 0 ed eseguendo un loc()
invert_vector = J(nrows(v), 1);
invert_vector[loc_vector] = 0;
invert_vector = loc(invert_vector);
quindi se hai concatenato i due vettori e li hai ordinati, dovrebbe essere solo 1::nrows()
dopodiché ho semplicemente impostato le righe per l'espressione if su +1 e l'espressione else su -1
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
e infine imposta la prima riga su 0
v[1] = 0;
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di dati@vince_faller ,
Grazie per la soluzione, puoi gentilmente spiegare il processo di pensiero e come funziona se non è chiedere troppo.
Vedo che stai utilizzando la combinazione di funzione lag_matrix, funzione mod e loc() ma non capisco bene la logica.
Apprezzerei molto una conoscenza approfondita della logica in modo da poter apprendere il processo (di nuovo solo se non è chiedere troppo)
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiNon è esattamente super facile da usare, ma anche tutti questi passaggi sono ancora ~ 3 volte più veloci (436:135 us) sul mio computer quando eseguo il vettore rispetto alla colonna. Ci sono sicuramente delle ottimizzazioni che potresti fare per renderlo anche più veloce. Quando l'ho messo a 1000 righe era ~ 4 volte più veloce (1057:227us). Inoltre, a quanto pare si sono sbarazzati di Apply, colpa mia.
dt = New Table( "Test" );
dt << New Column( "RandomList", Numeric, Continuous, <<SET values=""> 0, vettore_lag = vettore_lag[1 :: n - Abs( ritardo )]; nuovo_mat = vuoto_mat |/ mat[vettore_lag, 0]; , //altro vettore_lag = vettore_lag[Abs( ritardo ) + 1 :: n]; nuovo_mat = mat[vettore_lag, 0] |/ vuoto_mat; ); nuovo_mat; ); v = Colonna( dt, "ListaCasuale" ) << Ottieni valori; check_vettore = Column(dt, "DesFunc") << Ottieni valori; vettore_tempo = HPTime(); //lag il vettore lv = lag_matrix(v, 1); //modifica il vettore mod_vettore = lv / 2 - floor(lv/2); //trova le mod che desideri loc_vettore = loc(mod_vettore==0); //inverti per trovare le mod che non vuoi invert_ctor = J(nrows(v), 1); inverti_vettore[loc_vettore] = 0; inverti_vettore = loc(inverti_vettore); //assegna valori v[loc_vettore] = v[loc_vettore] + 1; v[inverti_vettore] = v[inverti_vettore] - 1; //imposta la prima riga a 0 v[1] = 0; vettore_tempo = HPTime()-vettore_tempo; mostra(all(v == check_vettore)); mostra(colonna_ora, vettore_ora);</SET>
Spero che questo aiuti un po'.
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di dati@vince_faller ,
Potete aiutarmi a implementare quanto segue in una matrice senza ciclo?
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))));Inoltre, non sono riuscito a trovare le funzioni apply() o applyOver() nel mio indice di scripting. Sto usando JMP 14. È una cosa di JMP Pro?
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiCosa stai effettivamente cercando di fare? Hai ragione sul fatto che le matrici sono generalmente più veloci, ma il loro ciclo (secondo la mia esperienza) di solito perde qualsiasi vantaggio. JMP 14 ora dispone delle funzioni apply() e applyOver() ma non ho avuto molta fortuna nell'utilizzarle.
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di dati@XanGregg , @Craige_Hales
Xan o Craige: se è possibile, ti chiederei gentilmente di pubblicare un post sul blog che spieghi in dettaglio come eseguire la vettorizzazione con numerosi esempi in JSL. Questo argomento è trattato approfonditamente in SAS, R, Matlab e altri ambienti. Mi piacerebbe vedere qualcosa di simile per JMP. Se esiste già qualcosa di simile, ti chiedo di attirare la mia attenzione su di esso.
Blog SAS - https://blogs.sas.com/content/iml/2013/05/15/vettorizzare-computazioni.html
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di dati@gzmorgan0 ,
Quello che sto cercando di chiedere è un modo per evitare il loop e fare affidamento sul codice vettorizzato. Si consiglia di sostituire i loop con funzioni di matrice per rendere il codice più efficiente ( https://community.jmp.com/t5/JMP-Blog/JSL-Tip-Replace-Loops-with-Functions-on-Matrices/ba- p/29783 ). Ciò è ottenuto in R attraverso le funzioni della famiglia apply e in Matlab attraverso alcune funzioni di matrice o funzioni personalizzate. Sto chiedendo se esiste un modo per implementare un codice così vettorizzato sulle matrici piuttosto che provare a scrivere un ciclo in questo caso per trovare il lag().
@gzmorgan0 wrote:
Uday,
Non so cosa stai chiedendo Puoi semplicemente fare riferimento alla riga j-1. Lo script mostra sia i risultati lag1 che quelli 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)
);
Nell'esempio che hai fornito, capisco sicuramente che è facile scrivere un ciclo e ottenere l'equivalente lag(), tuttavia, poiché la dimensione dei tuoi set di dati o il numero delle tue iterazioni aumentano, ciò rallenterà il tuo codice. Sto cercando un sostituto efficiente, ovvero l'equivalente vettorizzato dell'implementazione di operazioni ripetitive su matrici in JSL.
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiUday,
Non so cosa stai chiedendo Puoi semplicemente fare riferimento alla riga j-1. Lo script mostra sia i risultati lag1 che quelli 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)
);Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di dati@vince_faller ,
Grazie per la soluzione che hai offerto, c'è un modo per modificare questa funzione per ottenere solo la riga precedente anziché l'intera matrice?
Forse la domanda appropriata sarebbe qual è il formato vettorizzato del ciclo attorno a una matrice con la funzione, simile alle funzioni applicate in R che sono molto più veloci dei loop.
Ri: Alternativa a Lag() quando si lavora con matrici anziché tabelle di datiPer te funziona?
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);