J'essaie d'extraire les valeurs des colonnes des lignes sélectionnées dans une étiquette concaténée qui est utilisée pour annoter une ligne de référence ajoutée dans une distribution.
Le message d'erreur de concaténation est dû à une incompatibilité dans les dimensions de la liste. Les appels de tableau associatif utilisés pour collecter les valeurs des lignes sélectionnées suppriment les valeurs en double, ce qui génère des listes de valeurs uniques.
Mon objectif est d'obtenir le nom, l'âge et le poids d'une ligne sélectionnée donnée dans une chaîne qui peut être utilisée comme étiquette dans un appel d'ajout de référence ultérieur.
Avec l'approche actuelle, j'ai des codes d'erreur et dans certains cas un désalignement des données sans code d'erreur.
Exemple 1 - Condition d'erreur : trois poids uniques sont trouvés alors que les listes d'âges et de noms ne contiennent que deux éléments chacune dans les lignes sélectionnées. La troisième itération d'indexation échoue en raison des différences dans les dimensions de la liste.
Exemple 2 - Données mal alignées : trois lignes sont sélectionnées avec les noms Leslie et Patty. Il y a deux entrées avec le nom Patty, l'une âgée de 14 ans et pesant 85 ans, l'autre âgée de 16 ans et pesant 134 ans. L'une des entrées pour Patty et l'entrée pour Leslie ont toutes deux 14 ans. Le résultat des données mal alignées peut être vu si l'étiquette ne prend en compte que les listes pour le nom {"LESLIE", "PATTY"} et l'âge {14,16}. L'indexation ne créerait que deux entrées, la première est "Leslie ...14" la seconde est "Patty ...16" qui est une association correcte mais "Patty ...14" est manquant et les dimensions de la liste dépendent des données.
Dois-je supprimer les appels de tableau associatif et passer plutôt à une approche sous-ensemble/table ou dois-je réviser les appels de tableau associatif pour avoir des éléments de liste qui sont des listes avec le nom, l'âge et le poids capturés dans chaque itération ou pour chaque ligne sélectionnée ?
Merci,
Bryan
Code d'erreur lorsque les dimensions des listes sont dépassées :
l'argument doit être un caractère à la ligne 41 dans l'accès ou l'évaluation de 'Concat', mauvais argument( theAges[i] ), theNames[i] || /*###*/" ..." || /*###*/theAges[i] /*###*/

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
col_name_list = dt << get column names( string );
newColName = "State";
// New column: State
If( !Contains( col_name_list, newColName ),
Local( {dt, tempStrings},
dt = Data Table( "Big Class" );
dt << New Column( "State", Character, "Nominal" ) << Begin Data Update;
tempStrings = {"CA", "WA", "OR"};
For Each Row( dt, :State = tempStrings[Sequence( 1, 3, 1, 1 )] );
dt << End Data Update;
);
//Make it a double Patty :), another person with the same name.
dt << Add Rows( 1, At End );
//Cheat and use a constant of 41 for the last row index
dt[[41], {name, age, sex, height, weight, State}] = {{"PATTY", 16, "F", 57, 134, "WA"}};
);
// For illustration, select some names
dt << select where( Contains Item( :name, {"LESLIE", "PATTY"} ) );
dist = dt << Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :height ),
Quantiles( 0 ),
Summary Statistics( 0 ),
Horizontal Layout( 1 ),
Normal Quantile Plot( 0 ), // disable, if the user enabled it in the preferences :)
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
//);
),
By( :State )
);
// get all reports
// if there is a BY group, get the info - if there is none, put it into a list
If( Is List( dist ),
dists=dist;
myBys = Transform each ({myexpr} , dist << Get Where Expr, Arg(myExpr , 2 ))
, //no By
dists = Eval List( {dist} );
myBys= {};
);
//get the reports
distRPTs = Transform Each( {dist}, dists, Report( dist ) );
// Find the Midpoints of the bins the selected rows are in
dist << Save( "Level Midpoints" );
//loop though the By groups and add the reflines
For Each( {report, idx}, distRPTs,
//report = distRPTs[2]; idx=2;
selected rows = dt << get selected rows;
// there is a BY group -> restrict the selection
if(N Items(myBys),
Eval( Eval Expr( selected rows = dt << get rows where( Contains( Expr( selected rows ), Row() ) & :State == Expr( myBys[idx] ) ) ) );
);
theBins = (Associative Array( Column( dt, N Cols( dt ) )[selected rows] )) << get keys;
theNames = (Associative Array( Column(dt, "name") [dt << get selected rows] )) << get keys;
theAges = (Associative Array( Column(dt, "age") [dt << get selected rows] )) << get keys;
theWeights = (Associative Array( Column(dt, "weight") [dt << get selected rows] )) << get keys;
For( i = 1, i <= N Items(theWeights), i++,
theLabels[i] = theNames[i] || " ..." || theAges[i] ;
);
);
dt << delete columns( N Cols( dt ) );Bonjour Bryan, vous pouvez utiliser une colonne de transformation pour préparer les résultats corrects, puis sélectionner les entrées dont vous avez besoin :

Voir plus...Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
col_name_list = dt << get column names( string );
newColName = "State";
// New column: State
If( !Contains( col_name_list, newColName ),
Local( {dt, tempStrings},
dt = Data Table( "Big Class" );
dt << New Column( "State", Character, "Nominal" ) << Begin Data Update;
tempStrings = {"CA", "WA", "OR"};
For Each Row( dt, :State = tempStrings[Sequence( 1, 3, 1, 1 )] );
dt << End Data Update;
);
//Make it a double Patty :), another person with the same name.
dt << Add Rows( 1, At End );
//Cheat and use a constant of 41 for the last row index
dt[[41], {name, age, sex, height, weight, State}] = {{"PATTY", 16, "F", 57, 134, "WA"}};
);
// For illustration, select some names
dt << select where( Contains Item( :name, {"LESLIE", "PATTY"} ) );
dist = dt << Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :height ),
Quantiles( 0 ),
Summary Statistics( 0 ),
Horizontal Layout( 1 ),
Normal Quantile Plot( 0 ), // disable, if the user enabled it in the preferences :)
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
//);
),
By( :State )
);
// get all reports
// if there is a BY group, get the info - if there is none, put it into a list
If( Is List( dist ),
dists=dist;
myBys = Transform each ({myexpr} , dist << Get Where Expr, Arg(myExpr , 2 ))
, //no By
dists = Eval List( {dist} );
myBys= {};
);
//get the reports
distRPTs = Transform Each( {dist}, dists, Report( dist ) );
// Find the Midpoints of the bins the selected rows are in
dist << Save( "Level Midpoints" );
dt << transform column ("label",Character, Formula (:name || " ..." || Char(age)));
//loop though the By groups and add the reflines
For Each( {report, idx}, distRPTs,
//report = distRPTs[2]; idx=2;
selected rows = dt << get selected rows;
// there is a BY group -> restrict the selection
if(N Items(myBys),
Eval( Eval Expr( selected rows = dt << get rows where( Contains( Expr( selected rows ), Row() ) & :State == Expr( myBys[idx] ) ) ) );
);
myLabels = Associative Array(:label[selected rows]) << get keys;
print(myLabels)
);
dt << delete columns( N Cols( dt ) );
Salut @hogi
J'ai combiné vos idées dans cet article et l'article associé sur l'ajout d'une ligne de référence.
La solution qui fonctionne pour aligner les bonnes informations sans perte de valeurs répétées tout en ajoutant correctement des bacs aux tracés de la pile consistait à préparer des listes à partir des champs de la table en indexant les lignes sélectionnées dans une boucle for imbriquée.
- Distribution des parcelles
- Collecter par critères dans un tableau pour chacun des tracés d'une instance dans le rapport (3 tracés pour chaque élément de données, 3 tableaux)
- Collecter les rapports dans un objet utilisé dans l'itération
- Ajoutez les points médians des données tracées (3 tracés, 3 colonnes ajoutées au tableau de données)
- Parcourez l'objet avec un For Each pour accéder et augmenter chaque tracé
- Initialiser les variables de liste pour les bacs et les étiquettes
- Sélectionnez les lignes de données en fonction de critères de base (par exemple, numéro de série)
- Affiner les lignes sélectionnées en fonction des critères correspondant aux critères Par dans les tracés
- Utilisez une boucle for pour autant de lignes sélectionnées
- Collectez les bacs à partir des colonnes médianes ajoutées (chaque parcelle a une colonne respective)
- Collectez les informations dans l'étiquette à partir des colonnes intéressantes (par exemple, date de mesure, numéro de série)
- Ajoutez une ligne de référence avec les informations collectées.
- Supprimez les colonnes médianes pour éviter les données obsolètes au cas où les paramètres de tracé de l'étape 1 changeraient.
Principaux changements qui ont aidé :
1. Passez d'un tableau associatif à des listes renseignées par itération pour éviter l'élimination des valeurs en double, en maintenant l'alignement.
2. Créez des variables distinctes pour chacune des conditions.
J'espère que cela m'aidera à boucler la boucle. Vos conseils sont appréciés. Ils ont permis mon apprentissage et mes progrès.