<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Salut tout le monde,
Je construis actuellement un outil d'analyse de données à l'aide de JMP. Fondamentalement, nous utiliserons JMP pour permettre à notre client d'interagir avec la sortie de simulation générée à l'aide d'un autre logiciel.
La sortie de la simulation est stockée dans plusieurs tables avec des caractéristiques différentes mais les mêmes identifiants. Par exemple, une table contient des valeurs de sortie globalement associées à 1 réplication de simulation, une table différente contient la sortie associée à chaque agent présent dans une réplication de simulation (et a donc plusieurs lignes par réplication), et une autre table peut contenir la sortie pour chaque pas de temps de chaque réplication de simulation (comprenant ainsi de nombreuses lignes par réplication). Ce que toutes les tables ont en commun, ce sont des colonnes avec des identifiants et des paramètres d'entrée.
Maintenant le défi : j'aimerais pouvoir créer un filtre de données qui filtre toutes les tables de données simultanément, (bien sûr cela se fait sur la base des informations qu'elles partagent (par exemple un identifiant)). Mon objectif sous-jacent est d'organiser les données dans le format de tableau le plus pratique tout en étant capable de présenter dynamiquement les informations de différents tableaux à l'aide de graphiques, etc.
Toutes les pensées que vous pourriez avoir, s'il vous plaît faites le moi savoir!
Merci d'avance
La JSL à :
http://support.sas.com/demosdownloads/downarea_t4.jsp?productID=109646
est plutôt ancien et (heureusement !) obsolète depuis que nous avons ajouté le "gestionnaire d'état de ligne" (dans JMP 10, je pense). Cela a une variété d'utilisations, et le code ci-dessous montre comment vous pouvez l'exploiter dans ce cas.
// ian.cox@jmp.com : 03Novembre2014
// Démonstration de la façon de lier plusieurs tables enfants à une table parent à l'aide d'un gestionnaire d'état de ligne
NomsDefaultToHere ( 1 ) ;
// Créer des tables à utiliser
dt1 = NouveauTable ( "Tableau 1" ,
NouvelleColonne ( "IDENTIFIANT" , Numérique , Continu , Valeurs (( 1 :: dix ) ` )) ,
NouvelleColonne ( "Réponse" , Numérique , Continu , Formule ( AléatoireNormal ( 0 , 1 )))
) ;
dt2 = NouveauTable ( "Tableau 2" ,
NouvelleColonne ( "IDENTIFIANT" , Numérique , Continu , Formule ( Entier aléatoire ( 1 , 5 ))) ,
NouvelleColonne ( "Attribut 2" , Numérique , Continu , Formule ( Entier aléatoire ( 0 , dix ))) ,
Ajouter des lignes ( 20 )
) ;
dt3 = NouveauTable ( "Tableau 3" ,
NouvelleColonne ( "IDENTIFIANT" , Numérique , Continu , Formule ( Entier aléatoire ( 1 , 11 ))) ,
NouvelleColonne ( "Attribut 3" , Numérique , Continu , Formule ( Entier aléatoire ( 0 , 100 ))) ,
Ajouter des lignes ( 30 )
) ;
// Fonction d'utilité:
// Étant donné une table de données, une colonne de celle-ci et une ou plusieurs valeurs dans cette colonne, sélectionne toutes les lignes correspondantes.
// Nécessité de permettre à 'col' d'être numérique (caractère), auquel cas 'vals' est une matrice (est une liste).
selectMatchingRows =
Fonction ({ dt , col , vals } ,
rows2select = [] ;
si ( EstMatrice ( vals ) ,
// 'col' est numérique
Pour ( je = 1 , je <= NRow ( vals ) , je ++,
rows2select = VConcat ( rows2select , dt << GetRowsWhere ( col == vals [ je ])) ;
)
,
// 'col' est un caractère
Pour ( je = 1 , je <= NIéléments ( vals ) , je ++,
rows2select = VConcat ( rows2select , dt << GetRowsWhere ( col == vals [ je ])) ;
)
) ;
dt << Sélectionner les lignes ( rows2select ) ;
) ;
// Créez un gestionnaire d'état de ligne à affecter à la table 'maître' (dt1). Autoriser plusieurs sélections de lignes.
propagateSelectionToOtherTables =
Fonction ({ X } ,
// Récupère les lignes qui ont été sélectionnées
lignes sélectionnées = dt1 << GetSelectedRows ;
Si ( NRow ( lignes sélectionnées ) > 0 ,
// Récupère les identifiants correspondants
identifiants = dt1 : IDENTIFIANT [ lignes sélectionnées ] ;
// Sélectionne les lignes correspondantes dans dt2
selectMatchingRows ( dt2 , Expr ( : IDENTIFIANT ) , identifiants ) ;
// Sélectionne les lignes correspondantes dans dt3
selectMatchingRows ( dt3 , Expr ( : IDENTIFIANT ) , identifiants ) ;
,
// Efface toute sélection existante
dt2 << EffacerSélectionner ;
dt3 << EffacerSélectionner ;
) ;
) ;
// Affecte le gestionnaire à dt1
rsh = dt1 << MakeRowStateHandler ( propagateSelectionToOtherTables ) ;
J'ai trouvé un moyen beaucoup plus efficace de traiter le problème que mon approche initiale.
Pour transférer l'état de la ligne (inclus et sélectionné) de dtglobal vers dt1, dt2, dt3, vous pouvez utiliser ce qui suit, cela fonctionne rapidement et dynamiquement même pour les grandes tables de données. Tout ce dont vous avez besoin est une colonne avec une "clé" correspondante (valeur numérique) dans chaque table.
// Transfère l'état de la ligne de dtglobal vers d'autres tables
statehandler = dtglobal << Make Row State Handler( statetransfer );
transfert d'état = Fonction({Y},
dt1 << effacer les états de ligne ;
dt2 << effacer les états de ligne ;
dt3 << effacer les états de ligne ;
excluderows = dtglobal << obtenir les lignes exclues ;
excludekeys = dtglobal:Key << obtenir les valeurs ;
excludekeys = excludekeys[excluderows] ;
dt1 << Sélectionnez Where( Contient( Matrix( excludekeys ), :Key ) );
dt1 << exclure ;
dt2 << Sélectionnez Where( Contient( Matrix( excludekeys ), :Key ) );
dt2 << exclure ;
dt3 << Sélectionnez Where( Contient( Matrix( excludekeys ), :Key ) );
dt3 << exclure ;
selectrows = dtglobal << obtenir les lignes sélectionnées ;
selectkeys = dtglobal:Key << obtenir les valeurs ;
selectkeys = selectkeys[selectrows] ;
dt1 << Select Where( Contient( Matrix( selectkeys ), :Key ) );
dt2 << Select Where( Contient( Matrix( selectkeys ), :Key ) );
dt3 << Select Where( Contient( Matrix( selectkeys ), :Key ) );
)
;
Merci pour votre réponse PMroz.
J'ai expérimenté quelque chose de similaire à cet exemple: http://support.sas.com/demosdownloads/downarea_t4.jsp?productID=109646 .
J'ai créé deux tables dont l'état d'inclusion/exclusion de la table 2 dépend de celui de la table 1 (à l'avenir, cela pourrait être étendu pour inclure également les autres états tels que sélectionné, visible, couleur, etc.).
Malheureusement, le résultat n'est pas encore robuste. Cela fonctionne parfois, mais après avoir filtré (inclure/exclure) quelques lignes ou fait autre chose, cela cesse de fonctionner. Je soupçonne que cela pourrait être lié à la table de données actuelle, mais je ne suis pas sûr. L'utilisation du script que j'ai écrit à partir de la fenêtre de script (et non intégré dans le tableau 1) est légèrement plus robuste mais échoue parfois à faire quoi que ce soit.
Toute réflexion sur la façon d'améliorer encore cette approche est grandement appréciée !
Exécutez simplement le script pour les deux tables de la pièce jointe pour jeter un coup d'œil par vous-même. Le script que j'utilise pour connecter les tables se trouve également au bas de la pièce jointe.
Bref résumé:
La table 1 et la table 2 ont une colonne RepID.
Si une ligne du tableau 1 est incluse/exclue, la colonne :Excluded le fait (pour une raison quelconque, la référence dt/dt2 est perdue après le lancement des tables, donc je la redéfinis ici) :
Formule(
Si(Exclus(État de la ligne(Ligne())),
dt = Table de données( "linktable1.jmp" );
dt2 = Table de données( "linktable2.jmp" );
Tableau de données actuel( dt );
1;
,
dt = Table de données( "linktable1.jmp" );
dt2 = Table de données( "linktable2.jmp" );
Table de données actuelle( dt );
0 ;
)
)
),
Ensuite, la colonne :parser fait ceci :
Si(:Exclu == 1, Eval(Analyse(:ScriptEx)), :Exclu == 0, Eval(Analyse(:ScriptInc)))
Qui fait référence à ce script (dans :ScriptEx):
RepIDex = dt:RepID[] ;
Excludelist = Liste();
Excludelist = As List( dt2 << Get rows Where( dt2:RepID == RepIDex ) );
Table de données actuelle ( dt2 );
Eval( For( i = 1, i <= N Items( Excludelist ), i++, Row State( Excludelist ) = État exclu( 1 ) ) );
Voir pièce jointe pour l'ensemble du script inc. les tables.