Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenAlle,
Gibt es eine Alternative zu lag(), die ich verwenden könnte, wenn ich mit Matrizen anstelle von Datentabellen arbeite? Im Wesentlichen möchte ich den Wert der vorherigen Zeile meiner Spalte in einer Matrix betrachten, um den Wert der aktuellen Zeile zu bestimmen. Dies kann leicht mit der Funktion lag() in einer Datentabelle erreicht werden. Was ist ein effektiver Weg außer der Schleife, um dies zu erreichen, wenn mit Matrizen gearbeitet wird?
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")))));Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenHier ist eine Variation von Vinces Lösung, mit der ich gespielt habe. Es könnte oder könnte Erfasst nicht die Anforderungen, sondern erklärt möglicherweise, wie Sie die erforderlichen Manipulationen durchführen.
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]
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenSicher.Wenn wir uns also Ihre Formel ansehen (außer der ersten Zeile = 0)
If( Mod( Lag( :RandomList ), 2 ) == 0,
:RandomList[Row()] + 1,
:RandomList[Row()] - 1
)
Ich sehe es als drei Teile: die Verzögerung, die Mod == 0-Prüfung der Verzögerung und den else-Ausdruck davon.
Also mache ich zuerst den Lag
lv = lag_matrix(v, 1);
dann bekomme ich den Mod-Vektor
mod_vector = lv / 2 - floor(lv/2);
Aber ich habe gerade festgestellt, dass Mod mit Vektoren funktioniert, also könntest du es tun
mod_vector = mod(lv, 2);
was deutlich schneller ist
dann erhalte ich dadurch einen booleschen Vektor
mod_vector == 0 und loc(), um die Zeilen zu finden, in denen mod(2) von lag(1) 0 ist
loc_vector = loc(mod_vector==0);
loc_vector sind die Zeilen, die Ihrer if-Anweisung entsprechen
Mod( Lag( :RandomList ), 2 ) == 0
Um dann die Zeilen der else-Anweisung zu erhalten, invertiere ich die Auswahl, indem ich einen Vektor aus allen Einsen erstelle, die loc_vector-Zeilen auf 0 setze und einen loc() ausführe.
invert_vector = J(nrows(v), 1);
invert_vector[loc_vector] = 0;
invert_vector = loc(invert_vector);
Wenn Sie also die beiden Vektoren zusammengefasst und sortiert haben, sollte es nur 1::nrows() sein.
Danach setze ich einfach die Zeilen für den if-Ausdruck auf +1 und den else-Ausdruck auf -1
v[loc_vector] = v[loc_vector] + 1;
v[invert_vector] = v[invert_vector] - 1;
und schließlich die erste Zeile auf 0 setzen
v[1] = 0;
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt Datentabellen@vince_faller ,
Vielen Dank für die Lösung. Können Sie bitte den Denkprozess und seine Funktionsweise erklären, wenn es nicht zu viel verlangt ist?
Ich sehe, dass Sie die Kombination aus lag_matrix-Funktion, mod-Funktion und loc() verwenden, aber ich verstehe die Logik nicht ganz.
Ich würde mich sehr über eine Erläuterung der Logik freuen, damit ich den Denkprozess erlernen kann (wiederum nur, wenn es nicht zu viel verlangt ist).
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenEs ist nicht gerade besonders benutzerfreundlich, aber selbst alle diese Schritte sind auf meinem Computer immer noch etwa dreimal schneller (436:135 us), wenn der Vektor im Vergleich zur Spalte ausgeführt wird.Es gibt auf jeden Fall Optimierungen, die Sie daran vornehmen könnten, um es auch schneller zu machen. Als ich es auf 1000 Zeilen umstellte, war es etwa viermal schneller (1057:227us). Außerdem haben sie offenbar Apply abgeschafft, mein Fehler.
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>
Hoffe das hilft ein wenig.
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt Datentabellen@vince_faller ,
Können Sie mir helfen, Folgendes in einer Matrix ohne Schleife zu implementieren?
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))));Außerdem konnte ich die Funktionen apply() oder applyOver() in meinem Skriptindex nicht finden. Ich verwende JMP 14. Handelt es sich um eine JMP Pro-Sache?
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenWas versuchst du eigentlich zu tun?Sie haben Recht, dass Matrizen normalerweise schneller sind, aber das Durchlaufen dieser Matrizen wird (meiner Erfahrung nach) normalerweise keinen Nutzen bringen.JMP 14 verfügt jetzt über die Funktionen apply() und applyOver(), aber ich hatte nicht viel Glück damit, sie zu verwenden.
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt Datentabellen@XanGregg , @Craige_Hales
Xan oder Craige – wenn es möglich ist, würde ich Sie tatsächlich bitten, einen Blog-Beitrag zu verfassen, der detailliert beschreibt, wie die Vektorisierung mit zahlreichen Beispielen in JSL durchgeführt wird. Dieses Thema wird in SAS, R, Matlab und anderen Umgebungen ausführlich behandelt. Ich würde gerne etwas Ähnliches für JMP sehen. Falls etwas Ähnliches bereits existiert, würde ich Sie bitten, mich darauf aufmerksam zu machen.
SAS-Blogs - https://blogs.sas.com/content/iml/2013/05/15/vectorize-computations.html
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt Datentabellen@gzmorgan0 ,
Was ich zu verlangen versuche, ist eine Möglichkeit, die Schleife zu vermeiden und sich auf vektorisierten Code zu verlassen. Es empfiehlt sich, Schleifen durch Matrixfunktionen zu ersetzen, um den Code effizienter zu gestalten ( https://community.jmp.com/t5/JMP-Blog/JSL-Tip-Replace-Loops-with-Functions-on-Matrices/ba-p/29783 ). Dies wird in R durch die Apply-Familienfunktionen und in Matlab durch einige Matrixfunktionen oder benutzerdefinierte Funktionen erreicht. Ich frage, ob es eine Möglichkeit gibt, einen solchen vektorisierten Code auf Matrizen zu implementieren, anstatt in diesem Fall zu versuchen, eine Schleife zu schreiben, um die Verzögerung () zu finden.
@gzmorgan0 schrieb:
Uday,
Ich weiß nicht, was Sie fragen. Sie können einfach auf die Zeile j-1 verweisen. Das Skript zeigt sowohl lag1- als auch diff1-Ergebnisse an.
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)
);
In dem von Ihnen bereitgestellten Beispiel verstehe ich definitiv, dass es einfach ist, eine Schleife zu schreiben und das lag()-Äquivalent zu erhalten. Wenn jedoch die Größe Ihrer Datensätze oder die Anzahl Ihrer Iterationen zunimmt, wird dies Ihren Code verlangsamen. Ich suche nach einem effizienten Ersatz, dh einem vektorisierten Äquivalent zur Implementierung sich wiederholender Operationen an Matrizen in JSL.
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenUday,
Ich weiß nicht, was Sie fragen. Sie können einfach auf die Zeile j-1 verweisen. Das Skript zeigt sowohl lag1- als auch diff1-Ergebnisse an.
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)
);Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt Datentabellen@vince_faller ,
Vielen Dank für die von Ihnen angebotene Lösung. Gibt es eine Möglichkeit, diese Funktion so zu ändern, dass nur die vorherige Zeile und nicht die gesamte Matrix abgerufen wird?
Vielleicht wäre die passende Frage, was das vektorisierte Format für das Durchlaufen einer Matrix mit der Funktion ist – ähnlich wie beim Anwenden von Funktionen in R, die viel schneller als Schleifen sind.
Betreff: Alternative zu Lag() beim Arbeiten mit Matrizen statt DatentabellenGeht das für dich?
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);