Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenIch suche nach einem JSL-Skript, das Folgendes tut:
-
Ruft die aktuell ausgewählten Spalten in der aktiven Datentabelle ab.
-
Nimmt die erste ausgewählte Spalte .
-
Fordert den Benutzer auf, einen regulären Ausdruck einzugeben .
-
Wählt nur die Zeilen in der Tabelle aus, deren Wert in dieser Spalte mit dem regulären Ausdruck übereinstimmt .
-
Öffnet ein Datenansichtsfenster, in dem nur die übereinstimmenden Zeilen angezeigt werden.
Ist das mit JSL möglich?
Automatisierung und SkriptingDatenzugriffBetreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenEs ist möglich. Was haben Sie versucht?
Dies ist ein sehr einfaches Beispiel, dem alle Prüfungen fehlen, die implementiert werden könnten (und höchstwahrscheinlich sollten).
Names Default To Here(1);
dt = Current Data Table();
col = (dt << Get Selected Columns("String"))[1]; // I suggest dropping non-character columns
run_expr = Expr(
rgx_pattern = teb << Get Text; // You could check if the pattern is valid regex
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
// add check if any rows have been selected
dt << Data View; // If linked subset is fine, that is most likely better as it can avoid using select where
dt << Clear Select;
wait(0);
);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("")
),
Lineup Box(N Col(1),
Button Box("OK",
run_expr
),
Button Box("Cancel")
)
)
);
Write();
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenDas funktioniert, danke.
Ehrlich gesagt habe ich keinen Code eingefügt, weil mein Versuch nicht sehr nah dran war und einige grundlegende Missverständnisse über JSL aufdeckt, die wahrscheinlich daher rühren, dass ich GUI-Skripting mit AppleScript und Matlab gelernt habe.
Ich hätte die Liste der ausgewählten Spaltennamen erhalten und die erste ausgewählt, aber dann hätte ich eine Art "Dialogfeld anzeigen"-Funktion erwartet, die einen String zurückgibt, aber die gibt es anscheinend nicht und zwingt einen zu dieser Syntax für neues Fenster/Listenfeld/Schaltflächenausdruck. Das war für mich ziemlich unintuitiv, ergibt aber jetzt, wo ich verstehe, was es bewirkt, mehr Sinn. Ich habe ChatGPT ausprobiert, aber es hat lange Skripte erstellt, die überhaupt nicht ausgeführt wurden.
Ein paar Fragen zu Ihrer Lösung, wenn Sie Zeit haben:
- Warum funktioniert die Schaltfläche „Abbrechen“ nicht? Ich vermute, weil Sie kein zweites Argument für den Aufruf von Button Box() haben. Aber welcher Ausdruck würde das aktuelle Fenster schließen? Schließen()? Ich habe „Button Box ( „Abbrechen“ , Schließen ())“ ausprobiert, aber es gibt einen Fehler, den ich nicht verstehe. Ich habe Ihren Ansatz nachgeahmt und „Fenster schließen“ ausprobiert, was zu funktionieren scheint, aber ich vermute, es gibt eine sauberere Möglichkeit, dies zu tun.
- Ihr Aufruf „Get Selected Columns()“ hat „String“ als Argument, aber die Dokumentation zeigt, dass diese Funktion keine Argumente akzeptiert. Was bedeutet „String“ hier und woher wussten Sie, dass es akzeptiert wird oder was es bewirkt?
- Ich möchte direkt nach dem Ausführen des Skripts mit der Eingabe beginnen, aber der Fokus ist nicht an der richtigen Stelle. Ich habe nach dem Ausdruck „nw=...“ „teb << SetFocus;“ ausprobiert, aber JMP meldet, dass Texteingabefelder diese Meldung nicht verstehen.
- Ist es möglich, bei Regex die Groß-/Kleinschreibung zu ignorieren, und wenn ja, wie? (Ich habe versucht, „ " zu den Regex-Argumenten gemäß der Dokumentation, aber es kommt zu einem Fehler.)
- Ist es möglich, durch die Eingabetaste das „OK“-Skript auszulösen, wobei das Tab-Feld fokussiert ist?
- Wenn der Benutzer keine Spalten ausgewählt hat, würde ich gerne die erste Zeichenspalte verwenden, aber nach etwa 20 verschiedenen Versuchen habe ich es aufgegeben, herauszufinden, welche Spalte das ist.
- Ich würde es vorziehen, wenn die Teilmenge der Datenansicht verknüpft wäre. Ändert das den Ansatz?
Folgendes habe ich bisher:
Names Default To Here(1);
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns("String");
if(N Items(selCols)==0, selCols = dt << get column names("String") );
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt << Data View; // I prefer a linked subset, what changes here?
dt << Clear Select;
wait(0);
nw << Close Window;
);
close_expr = Expr(nw << Close Window);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("", <
<SET width=""></SET>
<P>Ich würde gerne Big Class öffnen, das Skript ausführen und dann "ob.+t" eingeben.<ENTER> " und lasse eine Datenansicht nur der beiden Roberts anzeigen. Im Moment ist es fast so weit – nachdem ich das Skript ausgeführt habe, muss ich die Tabulatortaste drücken, dann OB.+T und dann zweimal die Eingabetaste.</ENTER></P>
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmen- Ich habe ein möglichst minimales Beispiel erstellt, sodass „Abbrechen“ keinen Ausdruck zum Schließen des Fensters enthält.
- Ich habe gerade ausprobiert, ob "String" wie bei << get column names() funktioniert, und das tut es. Testen Sie es ohne den "String"-Wert und sehen Sie, was Sie erhalten (Referenzen statt Strings). Meiner Meinung nach ist die Arbeit mit Spaltenreferenzen ein Albtraum, daher verwende ich immer Strings mit Spaltennamen und konvertiere sie bei Bedarf. Aber es bleibt Ihnen überlassen, ob Sie Referenzen (oder wie auch immer diese Doppelpunkt-Syntax lautet) bevorzugen.
- Ich denke, Sie müssen auf die Tabulatortaste zurückgreifen, es sei denn, Sie möchten komplizierte Workarounds verwenden . Erlauben Sie die Verwendung von SetFocus mit interaktiven Anzeigeelementen (TextEditBox, Button …).
- Sie könnten Benutzereingaben in Lowercase() umwandeln und die Spaltenreferenz mit Lowercase() umschließen. Oder Sie könnten, wenn Sie INGORECASE verwenden, die Standarderfassungsgruppe zu Regex() hinzufügen: Regex("ABCD", "d", "\0", Groß-/Kleinschreibung ignorieren)
- Sie könnten die Funktion << Set ausprobieren, die Ihren Anforderungen entspricht. Sie führt das Skript beim Commit aus und sollte durch die Eingabetaste ausgelöst werden (ebenso wie das Klicken außerhalb des Textbearbeitungsfelds).
-
<< Get Column Names(Character, String)[1]
-
r = dt << Get Rows Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt_subset = dt << Subset(Rows(dt), Selected Columns(0), Link to original data table(1));
Es gibt zahlreiche Verbesserungsmöglichkeiten, aber welche, hängt vom tatsächlichen Anwendungsfall ab.
Bearbeiten: Link zur Originaldatentabelle(1) zur Teilmenge hinzugefügt
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenAusgezeichnet, vielen Dank!
Nur noch eine Frage: Wenn mehrere Spalten ausgewählt sind, möchte ich den regulären Ausdruck auf die als Strings verknüpften Spaltenwerte anwenden. Wenn keine Spalten ausgewählt sind, möchte ich dasselbe auf *alle* Spalten anwenden. Dies ahmt das Verhalten von egrep auf der Tabelle effektiv nach. Ist das realistisch machbar? Siehe die kommentierte Zeile unten für meinen ersten Versuch. Allerdings werden nicht nur die Werte aus den ausgewählten Spalten abgerufen, sodass es noch nicht so weit ist (und nicht funktioniert).
Names Default To Here( 1 );
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns( "String" );
If( N Items( selCols ) == 0,
selCols = dt << Get Column Names( "String" )
);
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where( !Is Missing( Regex( Column( dt, col )[Row()], rgx_pattern, "1", IGNORECASE ) ) );
// dt << Select Where( !Is Missing( Regex( Concat Items( dt << get Rows(Row())," "), rgx_pattern, "1", IGNORECASE ) ) );
dt << Data View;
Wait( 0 );
);
close_expr = Expr( nw << Close Window; Wait( 0 ); );
nw = New Window( "Table Egrep",
H List Box(
lb1 = Lineup Box( N Col( 2 ),
Text Box( "Select column to Enter regex pattern" ),
teb = Text Edit Box( "", Set Script( run_expr ), <
<SET width=""></SET>
<P>Zu Ihrer Information: Das obige „Set Script“ übernimmt die sofortige Ausführung bei „Enter“, was hervorragend funktioniert. Das einzige fehlende gewünschte Verhalten ist das oben beschriebene und die Notwendigkeit, „Tab“ zu drücken, um den Fokus in das Textbearbeitungsfeld zu setzen.</P>
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenEs könnte irgendwann langsam werden und Sie sollten eine Prüfung hinzufügen, dass nur Zeichenspalten ausgewählt sind, aber Sie können einen Ausdruck erstellen, um die Verkettung zu erstellen
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
dt << Select Columns({:name, :sex});
rgx_patter = "EF";
cols = dt << Get Selected Columns("String");
conc_expr = Expr(Concat());
For Each({colname}, cols,
Insert Into(conc_expr, Name Expr(As Column(dt, colname)));
);
regex_expr = Substitute(
Expr(!Is Missing(Regex(_conc_expr_, _rgx_pattern_, "\0", IGNORECASE))),
Expr(_conc_expr_), Name Expr(conc_expr),
Expr(_rgx_pattern_), rgx_pattern
);
rows_of_interest = dt << Get Rows Where(regex_expr);
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenSie können den Fokus auch mithilfe des modalen Fensters auf das Fenster zwingen, dies kann sich jedoch ziemlich negativ auf die Benutzererfahrung auswirken.
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenGerade als ich dachte, ich würde anfangen zu verstehen …
In der Dokumentation heißt es, dass Expr() „sein Argument unevaluiert zurückgibt“ – was mir ehrlich gesagt nichts sagt. Es klingt, als würde es einfach das zurückgeben, was Sie eingeben.
In Ihrem früheren Code sah es wie eine Subroutine aus, was damals Sinn ergab. Aber jetzt sehe ich „Expr(Concat())“ und kann nicht herausfinden, was tatsächlich verkettet wird. Später fügen Sie dann „Insert Into()“ in dieses Expr()-Objekt ein – aber woher weiß JMP, wo die Werte eingefügt werden sollen? Selbst ChatGPT hilft mir nicht weiter.
Es fühlt sich an, als würde man versuchen, einen Zaubertrick nachzumachen, indem man nur die Handbewegungen kopiert – frustrierend, insbesondere, da die Dokumentation für Get Row() genau das Verhalten zu versprechen scheint, das ich erreichen möchte.
Natürlich ist nichts davon Ihre Schuld, und ich weiß Ihre Hilfe wirklich zu schätzen. Ich denke, was ich jetzt habe, wird gut genug funktionieren. Danke!
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenHier wird nichts verkettet: Expr(Concat()). In diesem Fall können Sie dies als einen Sammler für Argumente betrachten, die nach Abschluss des Ausdrucks verkettet werden. Sie können es auch mit einer Liste erstellen und diese dann durch concat ersetzen.
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
val1 = "name";
val2 = "sex";
c = {};
Insert Into(c, Name Expr(As Column(dt, val1)));
Insert Into(c, Name Expr(As Column(dt, val2)));
show(c);
Substitute Into(c, Expr(List()), Expr(Concat()));
Show(c);
// Example use
Eval(EvalExpr(
dt << New Column("Concat", Character, Nominal, Formula(
Expr(Name Expr(c))
));
));
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenOk, ich glaube, ich habe es herausgefunden – dieses Skript ist im Grunde das tabellarische Äquivalent des Unix/Linux/Mac-Befehls „egrep“, d. h. es wählt/zeigt nur die Zeilen an, die mit einem vom Benutzer eingegebenen regulären Ausdruck (Suchzeichenfolge) übereinstimmen:
Names Default To Here( 1 );
If(
ex = New Window( "Enter search regex",
<
<MODAL></MODAL>
<P>Alle Schaltflächen funktionieren einwandfrei, und die Funktion ist selbst bei vielen tausend Zeilen recht schnell. Ich habe ein Add-In daraus erstellt und es mit cmd-shift-e (egrep) verknüpft und verwende es nun ständig. Natürlich bin ich offen für Verbesserungsvorschläge. Ich hoffe, das hilft jemandem!</P> <BR /> <P>(Und vielen Dank an <A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A> für seine Geduld und Einsicht!)</P>
Betreff: Schnelles Anzeigen der Datenansicht mit einer Teilmenge von Zeilen, die mit dem regulären Ausdruck übereinstimmenSieht gut aus! Ich würde ein paar kleine Änderungen vornehmen:
- Überprüfen Sie vor dem Öffnen des neuen Fensters, ob eine Tabelle geöffnet ist. Wenn nicht, führen Sie stop(); aus.
- Wenn keine Übereinstimmungen vorliegen, wird in der letzten Zeile ein Fehler ausgegeben. Sie können entweder die ausgewählte Zeilenanzahl überprüfen und stop() verwenden, wenn sie 0 ist, oder dem Benutzer die Information anzeigen, dass keine Übereinstimmungen vorliegen.
- << Zeilen abrufen, wo ist wahrscheinlich schneller als << Wo auswählen
- Eine zusätzliche Beschleunigung kann höchstwahrscheinlich durch die Auswertung der Spaltenreferenz erreicht werden
- << Bei der Validierung kann auch verwendet werden, wenn Sie möchten, dass der Benutzer einen neuen regulären Ausdruck eingibt, wenn der erste keine Übereinstimmungen hat
Mehr anzeigen...
Names Default To Here(1);
If(N Table() == 0,
stop(); // display error message to user if necessary
);
dt = Current Data Table();
nw = New Window("Enter search regex",
<
<MODAL>
0, col = selCols[1]; , col = Column(dt, 1) << get name; ); selrows = Eval(EvalExpr( dt << Get Rows Where(!Is Missing(Regex(Expr(NameExpr(As Column(dt, col))), inputRegex, "1", IGNORECASE))); )); If(N Rows(selrows) == 0, stop(); // display error message if necessary, this could also be done already within modal window (<< On Validate), if you wish to let user perform new search ); dt2 = dt << Subset(Rows(selrows), Selected Columns(0), Link to original data table(1), Output Table("")); // dt2 << Select Rows(1::NRows(dt2)); // to select rows if necessary
</MODAL>