Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurChers tous,
J'écris un script qui sera déployé auprès des utilisateurs de mon organisation pour effectuer des statistiques simples et rapides pour l'utilisateur sans avoir à appeler la plateforme de distribution. Le script est ci-dessous avec une capture d'écran de ce que j'ai actuellement, puis une liste des choses avec lesquelles j'ai des problèmes. Les utilisateurs exécuteront JMP 16.1, j'utilise JMP Pro 16.0. Toutes les machines sont des machines Windows 10, 64 bits.
Le but du script est d'afficher les colonnes numériques (je traiterai peut-être plus tard des colonnes catégorielles) et en fonction du bouton radio sélectionné, il effectuera quelques statistiques simples et affichera les résultats dans la même fenêtre avec une colonne intitulée Stats. pour le type de statistique calculée et Valeurs pour les résultats desdits calculs. La zone du panneau Résultats doit être mise à jour lors de la sélection du bouton radio après avoir sélectionné la colonne appropriée dans la zone du panneau Sélectionner une colonne.
Script JMP actuel (pour information, je le teste sur le fichier Big Class.jmp familier) :
Names Default To Here( 1 );
//Clear Symbols();
//the width of the column list box in pixels
lbWidth = 100;
dt = Current Data Table();
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};
StatsListC = {};
//Expression to do math
MathA = Expr(
response_col = Column( dt, Eval( Eval Expr( Expr( ycols ) ) ) );
ymean = Col Mean( response_col );
ystdev = Col Std Dev( response_col );
ymin = Col Min( response_col );
ymax = Col Max( response_col );
yrange = ymax - ymin;
yN = Col Number( response_col );
NumResultsA = {ymean, ystdev, ymin, ymax, yrange, yN};
);
//Expresseion for other math
MathB = Expr(
);
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
Voici ce que j'ai jusqu'à présent :

Voici la liste des choses avec lesquelles j'ai des problèmes :
- L'appel à Radio Box() répertorie le nom de la variable locale "StatsListA", etc. au lieu de répertorier réellement les statistiques qui seront calculées. Par exemple, le premier bouton radio doit avoir la liste suivante derrière lui : Mean, Std Dev, Max, Min, Range, N. Cela devrait également être pour StatsListB et StatsListC (je n'ai pas encore défini la liste C). Je ne sais pas comment le faire évaluer la liste prédéfinie que je fais en haut du code JSL. Je préférerais ne pas avoir à écrire chaque élément car je souhaiterais peut-être modifier les éléments de la liste et il est plus facile de modifier la variable locale StatsListX au lieu de modifier l'appel Radio Box() à chaque fois.
- Pour le moment, je préfère ne pas lister TOUTES les colonnes, mais juste des valeurs numériques. Lorsque je modifie l'option dans Col List Box() de All à Numeric (avec ou sans ""), j'obtiens une liste de colonnes vide. Je n'arrive pas à comprendre pourquoi cela se produit, alors qu'il ne devrait répertorier que les colonnes numériques lorsque cette option est définie.
- C'est le plus difficile à mon avis : comme mentionné précédemment, j'aimerais que les résultats dans la zone du panneau "Résultats" soient mis à jour avec une colonne à gauche "Statistiques" (qui répertorie les statistiques de StatsListX et les résultats de calcul pour celles-ci). stats dans la colonne de droite "Valeurs". Cela devrait être mis à jour à chaque clic sur un bouton radio. Donc, si vous regardiez à l'origine :height, mais que vous vouliez regarder :weight, vous sélectionneriez :weight puis cliqueriez sur l'un des boutons radio pour obtenir le résumé statistique correspondant. J'ai essayé de suivre l'exemple Set Function présenté ici, mais sans succès (je ne connais pas très bien l'appel Set Function).

Le Expr() pour MathA était destiné à être appelé en fermant la fenêtre d'origine et en ouvrant une nouvelle avec les résultats, mais après avoir fait quelques recherches supplémentaires dans les discussions JMP, j'ai découvert qu'il était possible de mettre à jour les champs dans une fenêtre existante, ce qui c'est ainsi que je préfère aborder ce problème. Donc, je sais que le codage original en haut de mon code n'est pas le bon code pour ce que j'ai l'intention de faire.
Toute aide à ce sujet est très appréciée.
Merci!,
DS
Ingénierie Qualité et ProcédésRe : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurC'est tellement chouette. Merci pour ce débat.
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurSalut tout le monde,
Je tiens à vous remercier pour vos suggestions de modifications continues. J'ai apporté quelques modifications au script et j'aime mieux la dernière version modifiée, j'apprécie donc vraiment les contributions des autres. Le script mis à jour sera publié à la fin de cette réponse. Ce nouveau script fournit également des statistiques récapitulatives pour les types de données Caractère. J'ai également légèrement modifié la disposition des panneaux.
@jthi , je pense que vos suggestions étaient très bonnes et je les ai intégrées. J'aime les noms d'en-tête colorés pour les statistiques de résultats. Aussi, semblable à ce que @ErraticAttack avait dans leur code, j'ai fait en sorte que les statistiques soient mises à jour lors de la sélection d'une nouvelle colonne OU de la sélection d'un nouveau résultat numérique. J'ai autorisé les résultats des statistiques de caractère à modifier leur taille verticale car il peut y avoir plusieurs niveaux, comme pour la table de données Big Class.jmp. Les statistiques catégorielles seront également mises à jour lors du passage à ce type de colonne, mais généreront une erreur si la colonne de caractères est sélectionnée et que quelqu'un clique ensuite sur une option de statistiques numériques. J'ai conservé la suggestion de largeur afin que la fenêtre ne continue pas à changer de taille en largeur. Désolé @ErraticAttack , je ne suis pas très familier à ce stade avec la définition de nouveaux espaces de noms et la façon dont vous avez modifié le code. Cela a l'air très utile et c'est une bonne façon d'aborder les choses, j'ai juste besoin d'apprendre à le faire correctement.
Je suis sûr qu'il existe d'autres suggestions sur la façon d'améliorer cela, en particulier l'esthétique. Si tel est le cas, postez, mais assurez-vous de me taguer pour que je sache qu'il y a eu une mise à jour de cette discussion. Merci encore à tous pour vos suggestions d'améliorations.
Merci!,
DS
ci-dessous
//GUI for quickly reporting statistics written by D. Schmidt, ver1.5
//Thanks to JMP User community members: jthi, ian_jmp, and ErraticAttach for helpful suggested changes.
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 217;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsList1 = {"µ", "σ", "Max", "Min", "Range(Δ)", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N 0", "Prop 0", "Prop non-0"};
maxStatCount = Max( N Items( StatsList1 ), N Items( StatsList2 ), N Items( StatsList3 ) );
//RadioBox() arguments
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
rbcArg = {"Select for categorical columns"};
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);
statZero = Expr(
N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
CatStats = Expr(
coltype = tempCol << Get Data type;
If( coltype == "Character",
catdist = dt << Distribution( Nominal Distribution( Column( tempCol ) ), Invisible );
rpt_catdist = catdist << Report;
lvl = rpt_catdist[String Col Box( 1 )] << Get;
Count = rpt_catdist[Number Col Box( 1 )] << Get;
Prob = rpt_catdist[Number Col Box( 2 )] << Get;
SummNMiss = rpt_catdist[List Box( 7 )][2] << Get Text;
SummLvl = rpt_catdist[List Box( 8 )][1] << Get text;
numNMiss = Num( SummNMiss );
numLvl = Num( SummLvl );
catdist << Close Window;
);
Insert Into( lvl, {"N Missing", "N Levels"} );
Insert Into( Count, numNMiss );
Insert Into( Count, numLvl );
);
//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurSalut @jimloughlin ,
Je pense que c'était juste un code de débogage qui @jthi utilisait en fournissant ses suggestions de modifications à mon code d'origine que j'ai publié. J'en publie une mise à jour qui prend en compte certaines modifications suggérées par d'autres personnes qui ont écrit sur ce fil. Je vous marquerai lorsque je publierai le script mis à jour. Je le fais fonctionner très bien avec la table de données Big Class.jmp.
Merci!,
DS
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurJe mets mes deux cents ici.Il est souvent préférable de séparer le script autant que possible en unités ou fonctions logiquement isolées.À cette fin, je trouve préférable de supprimer la logique de l’arborescence d’affichage et d’aplatir autant que possible les définitions de fonctions.
Dans mon exemple de solution ci-dessous, vous verrez que toutes les fonctions sont limitées au soi espace de noms et que la première ligne de chaque fonction couvre l'espace de noms soi espace de noms.En pratique, ce que j'ai fait, c'est créer un wrapper de méta-programmation qui le fait automatiquement, de sorte que je n'ai pas à définir explicitement le soi espace de noms ou inclure le self = Espace de noms( "nom" ) line comme premier argument de chaque fonction.Si vous créez de nombreuses interfaces graphiques interactives, vous souhaiterez peut-être faire quelque chose de similaire, car cela économisera beaucoup de travail.Cela présente également l'avantage de ne pas avoir besoin d'envelopper le script dans un Eval( Eval Expr( "<CODE>" ) ) bloc.
De plus, si vous suivez cette voie, je trouve qu'il est plus simple de produire un wrapper pour les boîtes d'affichage intégrées qui peut appeler directement le soi fonctions et ne pas avoir besoin de mettre autant de passe-partout dans le << Définir la fonction() messages.
/* quick stats */
self = New Namespace();
self:tool name = "Quick Stats";
Eval( Eval Expr(
self:initialize = Function( {}, // called before the display tree is generated
self = Namespace( Expr( self << Get Name ) );
self:table = Current Data Table();
self:radio inputs = {
"Mean, Std Dev, Max, Min, Range, N",
"Quantiles: 0.05, 0.25, 0.50, 0.75, 0.95",
"N, N Missing, N Zero, Prop 0, Prop non-0"
};
self:stat list = {
{"Mean", "Std Dev", "Max", "Min", "Range", "N"},
{"5%", "25%", "50%", "75%", "95%"},
{"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"}
};
1
);
self:content = Function( {}, // holds the display tree
self = Namespace( Expr( self << Get Name ) );
self:container = H Splitter Box(
V List Box(
H List Box(
Lineup Box( N Col( 1 ), Spacing( 0 ),
Spacer Box( <<SET auto="" stretching=""></SET>self:window << Update Window;
self:finalize();
) );
self << Get Name;
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurLorsque j'exécute statsstart.jcl, j'obtiens l'erreur suivante :
Nom non résolu : tempCol{1} dans l'accès ou l'évaluation de 'tempCol' , tempCol/*###*/
Peut-être parce que j'utilise la version 13.2.1 ?
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurUne fois que le script fonctionne comme vous le souhaitez, il y a quelques éléments visuels que je considérerais :
- La taille du tableau change et fait "rebondir" un peu la fenêtre
- Si l'utilisateur n'a sélectionné aucune colonne, il y aura une erreur
- Si aucune table de données n'est ouverte, vous pouvez arrêter l'exécution du script et informer l'utilisateur
- Si l'utilisateur modifie la colonne dans la zone de liste Col, vous devriez peut-être soit recalculer les statistiques avec la sélection actuelle de la zone radio, soit vider la table.
Quelques idées :
- Pour la zone du panneau Résultats. Vous pouvez utiliser Définir les largeurs pour empêcher le tableau de modifier la taille horizontale et l'espace réservé masqué String Col Box avec une taille de liste prédéfinie pour empêcher les changements de taille verticale.
- Sélectionnez la zone du panneau Colonnes. Vous pouvez ajouter Max Selected(1) pour empêcher l'utilisateur de sélectionner plusieurs colonnes.
- Choisissez la zone du panneau Statistiques rapides. Une sorte de "gestion des erreurs" si l'utilisateur n'a sélectionné aucune colonne.
Script complet avec quelques modifications :
Voir plus...
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurSalut @jthi et @ian_jmp ,
Merci à vous deux pour votre aide précieuse ! Merci pour les deux derniers conseils @jthi , j'ai pu surmonter le "problème" alphabétique du tableau associatif. J'aime le pouvoir des AA, je peux voir où ils peuvent être utiles, mais j'ai besoin de maintenir un certain ordre à cause des utilisateurs.
J'ai pu apporter les modifications avec la suggestion de listes et votre suggestion pour le problème Count Zero que j'ai eu. Merci! Le code fonctionne comme prévu, je vais maintenant devoir le développer pour créer des colonnes catégorielles, puis interroger mes utilisateurs pour voir de quelle liste réelle de statistiques ils ont besoin.
Merci encore pour votre aide! Le code de travail (au moins pour les colonnes numériques) est ci-dessous.
Merci!,
DS
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);
statZero = Expr(
N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateur1. En raison de l'utilisation du tableau associatif, les statistiques seront réorganisées. Vous pourriez peut-être simplement utiliser des listes et modifier le référencement pour utiliser des index
2. Modifier la façon dont vous calculez les valeurs 0 pourrait fonctionner. Vous pouvez par exemple utiliser l'exemple Loc() avec N Items() :
statZero = Expr(N Items(Loc(tempCol << get as matrix, 0)));

Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurSalut @jthi et @ian_jmp ,
Merci beaucoup à vous deux pour vos commentaires rapides ! Vos suggestions ont très bien fonctionné et j'ai pu faire beaucoup plus de progrès. Maintenant, j'ai des problèmes avec seulement deux choses probablement très simples, j'inclus le code mis à jour ci-dessous. Juste pour info, j'ai supprimé certaines valeurs dans :height et ajouté des zéros dans :height pour le tester
Problèmes:
- Lorsqu'il liste les statistiques, il les fait par ordre alphabétique, je souhaite conserver l'ordre que j'ai défini dans mes listes, est-ce possible ?
- J'essaie de calculer la proportion zéro et non nulle en comptant d'abord le nombre de zéros. Malheureusement, cela ne fonctionne pas très bien. Je peux mettre le résumé dans un Expr(), mais je ne parviens pas à définir le tableau associatif et je n'obtiens pas les bons calculs ultérieurs. Je suis sûr qu'il existe un moyen plus simple de procéder, mais je n'ai trouvé aucune commande directe dans JSL pour ne compter que les zéros. J'ai entré manuellement 5 valeurs manquantes et 7 valeurs nulles. Ainsi, le prop-non-zéro devrait être de 0,8 et le prop-zéro devrait être de 0,2.
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsListC = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};
//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsListA, ", " ), Concat Items( StatsListB, ", " ), Concat Items( StatsListC, ", " )} );
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);<BR /><BR />//Here's where I'm having trouble with the N Zero and proportions zero and non-zero.
Expr(
Summarize( dt, eg = By( tempCol ), em = Count( tempCol ) )
);
PropTemp1 = Expr(
Associative Array( eg, em )
);
statZero = Expr( PropTemp1["0"] );
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
maths = Associative Array();
maths["StatListA"] = Associative Array( StatsListA, {statMean, statStd, statMax, statMin, statRange, statN} );
maths["StatListB"] = Associative Array( StatsListB, {., statQ95, statQ75, statQ50, statQ25, statQ5} );
maths["StatListC"] = Associative Array( StatsListC, {statN, statMiss, statZero, statProp0, statPropn0} );
rbOptions = maths << Get Keys;
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
Merci encore pour votre aide jusqu'à présent et j'espère que vous pourrez nous aider avec ces autres petites choses.
Merci!,
DS
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurConcernant le point 1., et en ajoutant juste un peu à la réponse de @jthi , tu peux faire:
Names Default To Here( 1 );
//the width of the column list box in pixels
lbWidth = 100;
dt = Open("$SAMPLE_DATA/Big Class.jmp");
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};
//RadioBox() argument
rbArg = EvalList({ConcatItems(StatsListA, ", "), ConcatItems(StatsListB, ", ")});
//Window
New Window( "GUI for quick stats",
Panel Box( "Select Columns", ColListData = Col List Box( dt, all, <<SET data="https://community.jmp.com/" type=""></SET>
Re : Aide à la création de scripts pour une fenêtre interactive qui se met à jour en fonction des choix de l'utilisateurJ'ai fait quelques tests rapides et joint le script. Il a des idées possibles sur la manière d'aborder cela, mais ce ne sont peut-être pas les meilleures solutions.
1. Géré avec des tableaux et des expressions associatifs.
2. J'ai dû utiliser une syntaxe étrange pour cette ColListData = Col List Box(dt, All, <
3. Set Function gère cela avec Evals.
Le script ci-joint donnera la meilleure idée de la façon dont j'ai abordé cela pour le moment.
