Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreJe recherche un script JSL qui fait ce qui suit :
-
Obtient les colonnes actuellement sélectionnées dans la table de données active.
-
Prend la première colonne sélectionnée .
-
Invite l' utilisateur à saisir une expression régulière .
-
Sélectionne uniquement les lignes du tableau où la valeur de cette colonne correspond à l'expression régulière .
-
Ouvre une fenêtre d'affichage des données affichant uniquement les lignes correspondantes.
Est-ce possible avec JSL ?
Automatisation et scriptsAccès aux donnéesRe : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreC'est possible. Qu'as-tu essayé ?
Il s'agit d'un exemple très basique qui manque de tous les contrôles qui pourraient (et devraient probablement) être mis en œuvre.
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 : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreÇa marche, merci.
Pour être honnête, je n'ai inclus aucun code car ma tentative n'était pas très proche et expose certains malentendus fondamentaux sur JSL qui viennent probablement de mon apprentissage des scripts GUI à partir d'AppleScript et de Matlab.
J'aurais bien récupéré la liste des noms de colonnes sélectionnés et choisi la première, mais je m'attendais à une fonction « Afficher la boîte de dialogue » renvoyant une chaîne, mais celle-ci n'existe apparemment pas et force l'utilisateur à utiliser une syntaxe de type « nouvelle fenêtre/liste déroulante/expression de bouton », assez peu intuitive pour moi, mais plus claire maintenant que je comprends son fonctionnement. J'ai essayé ChatGPT, mais il créait de longs scripts qui ne s'exécutaient pas du tout.
Quelques questions sur votre solution, si vous avez le temps :
- Pourquoi le bouton « Annuler » ne fait-il rien ? Je suppose que vous n'avez pas de second argument pour son appel à Button Box(), mais quelle expression fermerait la fenêtre actuelle ? Close() ? J'ai essayé « Button Box ( "Annuler" , Fermer ()) », mais le résultat est une erreur que je ne comprends pas. J'ai imité votre approche et essayé « Fermer la fenêtre », ce qui semble fonctionner, mais je suppose qu'il existe une méthode plus simple.
- Votre appel « Get Selected Columns() » contient « String » comme argument, mais la documentation indique que cette fonction n'accepte aucun argument. Que signifie « String » ici, et comment saviez-vous qu'il serait accepté ? Quel est son rôle ?
- J'aimerais commencer à taper immédiatement après l'exécution du script, mais le focus n'est pas au bon endroit. J'ai essayé « teb << SetFocus; » après l'expression « nw=… », mais JMP indique que les zones d'édition de texte ne comprennent pas ce message.
- Est-il possible de rendre Regex insensible à la casse, et si oui, comment ? (J'ai essayé d'ajouter " " aux arguments Regex selon la documentation, mais cela génère une erreur.)
- Est-il possible de faire en sorte que le retour/entrée déclenche le script « Ok » avec la case teb focalisée ?
- Si l'utilisateur n'a pas de colonnes sélectionnées, j'aimerais utiliser la première colonne de caractères, mais après environ 20 tentatives différentes, j'ai abandonné l'idée de déterminer de quelle colonne il s'agit.
- Je préférerais que le sous-ensemble de la vue des données soit lié, cela change-t-il l'approche ?
Voici ce que j'ai jusqu'à présent :
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>J'aimerais ouvrir Big Class, exécuter le script, puis taper "ob.+t<ENTER> " et faites-lui afficher une vue de données des deux Roberts seulement. Pour l'instant, c'est proche - après avoir exécuté le script, je dois appuyer sur Tab, puis sur OB.+T, puis sur Entrée deux fois.</ENTER></P>
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulière- J'ai créé un exemple aussi minimal que possible, donc Cancel ne contient pas d'expression pour fermer la fenêtre
- Je viens de vérifier si « String » fonctionne comme avec << get column names() et c'est le cas. Testez sans la valeur « String » et voyez ce que vous obtenez (des références au lieu de chaînes). À mon avis, travailler avec des références de colonnes est un cauchemar ; j'utilise donc toujours des chaînes de noms de colonnes et je les convertis si nécessaire. Mais c'est à vous de décider si vous préférez utiliser des références (ou toute autre syntaxe avec deux points).
- Je pense que vous êtes coincé avec l'onglet à moins que vous ne souhaitiez utiliser des solutions de contournement compliquées . Autorisez SetFocus à être utilisé avec des éléments d'affichage interactifs (TextEditBox, Button...)
- Vous pouvez mettre la saisie utilisateur en minuscules () et encapsuler la référence de colonne avec des minuscules (). Vous pouvez également ajouter le groupe de capture par défaut à Regex() lors de l'utilisation de INGORECASE : Regex("ABCD", "d", "\0", IGNORECASE)
- Vous pouvez essayer la fonction « Set » qui répond à vos besoins. Elle exécutera le script lors de la validation, et la fonction « Entrée » devrait déclencher cette action (tout comme un clic en dehors de la zone de saisie).
-
<< 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));
De nombreuses améliorations pourraient être apportées, mais leur nature dépend du cas d’utilisation réel.
Modifier : Ajout d'un lien vers la table de données d'origine (1) pour sous-ensemble
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreExcellent, merci !
Juste une dernière question : si plusieurs colonnes sont sélectionnées, je souhaite appliquer l'expression régulière aux valeurs des colonnes concaténées sous forme de chaînes. Si aucune colonne n'est sélectionnée, je souhaite appliquer la même méthode à *toutes* les colonnes. Cela reproduit le comportement d'egrep sur la table. Est-ce raisonnablement réalisable ? Voir la ligne commentée ci-dessous pour ma première tentative, mais elle n'extrait pas uniquement les valeurs des colonnes sélectionnées, ce qui n'est pas encore possible (et ne fonctionne pas).
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>Pour information, le script « Set » ci-dessus gère l'exécution immédiate sur « Entrée », ce qui fonctionne parfaitement. Le seul comportement souhaité manquant est celui décrit ci-dessus, et la nécessité d'appuyer sur « Tab » pour placer le focus dans la zone d'édition de texte.</P>
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreCela peut commencer à devenir lent à un moment donné et vous devriez ajouter une vérification que seules les colonnes de caractères sont sélectionnées, mais vous pouvez créer une expression pour créer la concat
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 : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreVous pouvez également forcer le focus à être dans la fenêtre en utilisant la fenêtre modale, mais cela peut être assez mauvais pour l'expérience utilisateur.
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreJuste au moment où je pensais commencer à comprendre…
La documentation indique que Expr() « renvoie son argument sans évaluation », ce qui, honnêtement, ne me dit rien. On dirait qu'elle renvoie simplement ce que vous lui transmettez.
Dans votre code précédent, cela ressemblait à une sous-routine, ce qui était logique à l'époque. Mais maintenant, je vois Expr(Concat()), et je n'arrive pas à comprendre ce qui est réellement concaténé. Ensuite, vous insérez Into() cet objet Expr() ; mais comment JMP sait-il où insérer les valeurs ? Même ChatGPT ne m'aide pas à comprendre.
C'est comme essayer de recréer un tour de magicien simplement en copiant les mouvements de la main - frustrant, d'autant plus que la documentation de Get Row() semble promettre exactement le comportement que j'essaie d'obtenir.
Bien sûr, ce n'est pas de votre faute, et j'apprécie vraiment votre aide. Je pense que ce que j'ai maintenant fonctionnera bien. Merci !
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreAucune concatène n'est effectuée ici : Expr(Concat()). Dans ce cas, il s'agit d'un collecteur d'arguments qui seront concaténés une fois l'expression construite. Vous pouvez également la construire avec une liste, puis la remplacer par 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 : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreOk, je pense que j'ai compris cela - ce script est fondamentalement l'équivalent tabulaire de la commande unix/linux/mac "egrep", c'est-à-dire sélectionner/afficher uniquement les lignes qui correspondent à une expression régulière saisie par l'utilisateur (chaîne de recherche) :
Names Default To Here( 1 );
If(
ex = New Window( "Enter search regex",
<
<MODAL></MODAL>
<P>Tous les boutons fonctionnent correctement et l'application est relativement rapide, même avec plusieurs milliers de lignes. Personnellement, j'en ai créé un module complémentaire, lié à cmd-Maj-e (egrep), et je l'utilise désormais en permanence. Je suis bien sûr ouvert à toute suggestion d'amélioration. J'espère que cela sera utile !</P> <BR /> <P>(Et un grand merci à <A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A> pour sa patience et sa perspicacité !)</P>
Re : Afficher rapidement la vue des données avec un sous-ensemble de lignes correspondant à l'expression régulièreÇa a l'air bien ! J'apporterais quelques petites modifications :
- Avant d'ouvrir la nouvelle fenêtre, vérifiez qu'une table est ouverte et si ce n'est pas le cas, exécutez stop();
- En l'absence de correspondance, la dernière ligne génèrera une erreur. Vous pouvez vérifier le nombre de lignes sélectionnées et utiliser stop() s'il est nul, ou afficher l'information indiquant qu'il n'y a pas de correspondance.
- << Obtenir les lignes où est probablement plus rapide que << Sélectionner où
- Une accélération supplémentaire peut probablement être obtenue en évaluant la référence de colonne
- << On Validate peut également être utilisé si vous souhaitez permettre à l'utilisateur de saisir une nouvelle expression régulière si la première n'a aucune correspondance
Voir plus...
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>