Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareSto cercando uno script JSL che faccia quanto segue:
-
Ottiene le colonne attualmente selezionate nella tabella dati attiva.
-
Prende la prima colonna selezionata .
-
Richiede all'utente di immettere un'espressione regolare .
-
Seleziona solo le righe nella tabella in cui il valore in quella colonna corrisponde all'espressione regolare .
-
Apre una finestra Visualizzazione dati che mostra solo le righe corrispondenti.
È possibile con JSL?
Automazione e scriptingAccesso ai datiRe: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareÈ possibile. Cosa hai provato?
Questo è un esempio molto elementare a cui mancano tutti i controlli che potrebbero (e molto probabilmente dovrebbero) essere implementati
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();
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareFunziona, grazie.
A dire il vero, non ho incluso alcun codice perché il mio tentativo non era molto vicino e mette in luce alcuni fraintendimenti fondamentali su JSL che probabilmente derivano dal fatto che ho imparato lo scripting GUI da AppleScript e Matlab.
Avrei ottenuto l'elenco dei nomi delle colonne selezionate, scegliendo la prima, ma poi mi aspettavo una sorta di funzione "visualizza finestra di dialogo" che restituisse una stringa, ma a quanto pare non esiste e ti costringe a questa sintassi nuova finestra/casella di riepilogo/espressione pulsante, che per me era piuttosto poco intuitiva, ma ora che ho capito a cosa serve ha più senso. Ho provato ChatGPT, ma creava script lunghi che non venivano eseguiti affatto.
Se hai tempo, ecco alcune domande sulla tua soluzione:
- Perché il pulsante "Annulla" non fa nulla? Presumo perché non hai un secondo argomento per la sua chiamata a Button Box(), ma quale espressione chiuderebbe la finestra corrente? Close()? Ho provato "Button Box ( "Annulla" , Vicino ())" ma restituisce un errore che non capisco. Ho imitato il tuo approccio e ho provato "Chiudi finestra", che sembra funzionare, ma immagino ci sia un modo più pulito per farlo.
- La tua chiamata "Get Selected Columns()" ha "String" come argomento, ma la documentazione mostra che la funzione non accetta argomenti. Cosa significa "String" in questo caso e come sapevi che sarebbe stata accettata o a cosa serve?
- Vorrei iniziare a digitare subito dopo aver eseguito lo script, ma il focus non è nel posto giusto. Ho provato a digitare "teb << SetFocus;" dopo l'espressione "nw=...", ma JMP dice che le caselle di modifica del testo non capiscono quel messaggio.
- È possibile fare in modo che Regex non faccia distinzione tra maiuscole e minuscole e, in tal caso, come? (Ho provato ad aggiungere " " agli argomenti Regex secondo la documentazione, ma genera un errore.)
- È possibile far sì che Invio attivi lo script "Ok" con la casella teb selezionata?
- Se l'utente non ha selezionato alcuna colonna, vorrei usare la prima colonna di caratteri, ma dopo circa 20 tentativi diversi ho rinunciato a capire di quale colonna si trattasse.
- Preferirei che il sottoinsieme della visualizzazione dati fosse collegato. Ciò cambia l'approccio?
Ecco cosa ho finora:
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>Mi piacerebbe aprire Big Class, eseguire lo script, quindi digitare "ob.+t<ENTER> " e fargli visualizzare una Vista Dati solo dei due Robert. Al momento è quasi perfetto: dopo aver eseguito lo script, devo premere Tab, poi OB.+T, poi Invio due volte.</ENTER></P>
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolare- Ho creato un esempio il più minimale possibile, in modo che Annulla non contenga l'espressione per chiudere la finestra
- Ho appena provato a vedere se "String" funziona come con << get column names() e funziona. Provalo senza il valore "String" e vedi cosa ottieni (riferimenti invece di stringhe). A mio parere, lavorare con i riferimenti di colonna è un incubo, quindi uso sempre stringhe di nomi di colonna e le converto quando necessario. Ma sta a te decidere se preferisci usare i riferimenti (o qualunque sia la sintassi dei due punti).
- Penso che tu sia costretto a usare la scheda, a meno che tu non voglia usare soluzioni alternative complicate . Consenti l'uso di SetFocus con elementi di visualizzazione interattivi (TextEditBox, Button...)
- Potresti usare Lowercase() per l'input utente e racchiudere il riferimento alla colonna con Lowercase(). Oppure, credo che potresti aggiungere il gruppo di acquisizione predefinito a Regex() quando usi INGORECASE: Regex("ABCD", "d", "\0", IGNORA MAIUSCOLO)
- Potresti provare << Set Function, che potrebbe fare al caso tuo. Eseguirà lo script al momento del commit e Invio dovrebbe attivarlo (così come fare clic al di fuori della casella di modifica del testo).
-
<< 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));
Ci sono molti miglioramenti che potrebbero essere apportati, ma la scelta dipenderà dal caso d'uso reale.
Modifica: aggiunto collegamento alla tabella dati originale (1) al sottoinsieme
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareOttimo, grazie!
Un'ultima domanda: se sono selezionate più colonne, vorrei eseguire l'espressione regolare sui valori delle colonne concatenati insieme come stringhe, e se non è selezionata alcuna colonna, vorrei fare la stessa cosa su *tutte* le colonne. Questo imita efficacemente il comportamento di egrep sulla tabella. È ragionevolmente fattibile? Vedi la riga commentata qui sotto per il mio tentativo iniziale, ma non estrae solo i valori dalle colonne selezionate, quindi non è ancora pronto (e non funziona).
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>Per vostra informazione, il comando "Set Script" qui sopra gestisce l'esecuzione immediata con "Invio", il che funziona alla grande. L'unica cosa che manca è il comportamento desiderato, ovvero la necessità di premere "Tab" per spostare il focus sulla casella di modifica del testo.</P>
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolarePotrebbe iniziare a rallentare a un certo punto e dovresti aggiungere un controllo per verificare che siano selezionate solo le colonne di caratteri, ma puoi creare un'espressione per creare la concatenazione
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);
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareÈ anche possibile forzare il focus sulla finestra utilizzando la finestra modale, ma questa soluzione può rivelarsi piuttosto negativa per l'esperienza utente.
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareProprio quando pensavo di aver iniziato a capire...
La documentazione dice che Expr() "restituisce il suo argomento non valutato", il che, onestamente, non significa nulla per me. Sembra che restituisca semplicemente qualsiasi cosa gli venga passata.
Nel tuo codice precedente, sembrava una subroutine, il che aveva senso all'epoca. Ma ora vedo Expr(Concat()) e non riesco a capire cosa venga effettivamente concatenato. Poi, più avanti, usi Insert Into() su quell'oggetto Expr(), ma come fa JMP a sapere dove inserire i valori? Nemmeno ChatGPT mi aiuta a capirlo.
Sembra di voler ricreare un trucco di magia semplicemente copiando i movimenti delle mani: frustrante, soprattutto perché la documentazione di Get Row() sembra promettere esattamente il comportamento che sto cercando di ottenere.
Naturalmente, niente di tutto questo è colpa tua, e apprezzo molto il tuo aiuto. Credo che quello che ho ora funzionerà abbastanza bene. Grazie!
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareQui non viene concatenato nulla. Expr(Concat()). In questo caso, puoi vederlo come un raccoglitore di argomenti che verranno concatenati dopo aver completato la costruzione dell'espressione. Puoi anche costruirla con una lista e poi sostituirla con concat.
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))
));
));
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareOk, credo di aver capito: questo script è fondamentalmente l'equivalente tabellare del comando "egrep" di Unix/Linux/Mac, ovvero seleziona/mostra solo le righe che corrispondono a un'espressione regolare immessa dall'utente (stringa di ricerca):
Names Default To Here( 1 );
If(
ex = New Window( "Enter search regex",
<
<MODAL></MODAL>
<P>Tutti i pulsanti funzionano correttamente ed è ragionevolmente veloce anche con migliaia di righe. Personalmente, ne ho creato un componente aggiuntivo e l'ho collegato a cmd-shift-e (egrep) e ora lo uso sempre. Naturalmente sono aperto a suggerimenti su come migliorarlo. Spero che questo aiuti qualcuno!</P> <BR /> <P>(E un grande ringraziamento a <A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A> per la sua pazienza e la sua intuizione!)</P>
Re: Mostra rapidamente la vista dati con un sottoinsieme di righe che corrispondono all'espressione regolareSembra fantastico! Farei qualche piccola modifica:
- Prima di aprire la nuova finestra, verificare che ci sia una tabella aperta e, in caso contrario, eseguire stop();
- Se non ci sono corrispondenze, l'ultima riga genererà un errore. È possibile controllare il conteggio delle righe selezionate e utilizzare stop() se è 0 oppure mostrare all'utente l'informazione che non ci sono corrispondenze.
- << Ottieni righe Dove è molto probabilmente più veloce di << Seleziona dove
- Un'ulteriore accelerazione può essere probabilmente ottenuta valutando il riferimento della colonna
- << On Validate potrebbe anche essere utilizzato se si desidera consentire all'utente di immettere una nuova espressione regolare se la prima non ha corrispondenze
Scopri di più...
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>