Bonjour, j'ai le défi suivant avec lequel j'ai du mal à écrire des scripts.
Ma table de données de départ ressemble à ci-dessous. Je voudrais multiplier Xi vers l'arrière à partir de col2 = 0 comme critère et mettre les nouvelles valeurs dans une nouvelle colonne.
col1 col2
X1 0
X2 y2
X3 y3
…
Xnyn
XX1 0
XX2 aa2
….
XXn yyn
….
….
Ma table de données finale ressemblerait à ceci :
col1 col2 col3
X1 0 Xn*Xn-1*……X3*X2*X1
X2 y2 Xn*Xn-1*…..X3*X2
X3 y3 Xn*Xn-1*….*X3
…
Xn et Xn
XX1 0 XXn*XXn-1*…..XX2*XX1
XX2 yy2 XXn*XXn-1*…..XX2
….
XXn yyn XXn
….
….
Quelqu'un peut-il aider s'il vous plaît? Très apprécié!
Les calculs que vous voulez sont très faciles à faire si les données sont inversées, alors voici un petit script qui calculera les valeurs en utilisant cette idée
names default to here(1);
// create the sample table
dt = New Table( "example",
Add Rows( 10 ),
New Column( "col1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [1, 2, 3, 2, 4, 5, 6, 7, 8, 9] ),
Set Display Width( 48 )
),
New Column( "col2",
Character( 1 ),
"Nominal",
Set Values( {"x", "x", "x", "y", "y", "y", "y", "z", "z", "z"} ),
Set Display Width( 45 )
)
);
// JSL to create the column you want
// create a new column to preserve the order of the data
dt << new column("origRow", formula(row()));
dt:origRow << delete formula;
// Reverse the order of the data
dt << sort(by(:origRow), order(descending), replace table(1));
// create the new column
dt << new column( "col3", formula(
If( Row() == 1, x = :col1 );
If( Lag( :col2 ) != :col2,
x = :col1,
x = x * :col1
);
x;
));
// Since the formula is dependent on the order of the data, the formula needs
// to be removed and the values set to static values
dt:col3 << delete formula;
// reorder the data table back to the original order and delete the origRow column
dt << sort(by(:origRow), order(ascending), replace table(1));
dt << delete columns(:origRow);
Et voici un morceau de JSL qui va créer la nouvelle colonne sans trier
Names Default To Here( 1 );
// create the sample table
dt = New Table( "example",
Add Rows( 10 ),
New Column( "col1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [1, 2, 3, 2, 4, 5, 6, 7, 8, 9] ),
Set Display Width( 48 )
),
New Column( "col2",
Character( 1 ),
"Nominal",
Set Values( {"x", "x", "x", "y", "y", "y", "y", "z", "z", "z"} ),
Set Display Width( 45 )
)
);
// create the new column
dt << New Column( "col3b" );
:col3b[N Rows( dt )] = :col1[N Rows( dt )];
For( i = N Rows( dt ) - 1, i >= 1, i--,
If( :col2[i + 1] != :col2[i],
:col3b[i] = :col1[i],
:col3b[i] = :col3b[i + 1] * :col1[i]
)
);
Salut Jim @txnelson
Cela a en fait fonctionné sur une table plus petite (c'est-à-dire plusieurs milliers de lignes). Merci.
Le "nouveau" problème que j'ai est que ma table de données est très volumineuse. Lorsque j'ai intégré la formule dans la nouvelle colonne et cliqué sur "appliquer", le programme s'est bloqué et j'ai dû tuer jmp pour sortir.
Alors que je survole la formule, voici le message d'avertissement concernant la "table de données actuelle".
"Current data table() a des effets secondaires et est généralement inapproprié pour être utilisé dans une formule. Si cela est nécessaire, vous pouvez utiliser expr ou eval pour empêcher l'exécution dans les formules...."
Mes compétences en script sont très limitées. Merci pour votre aide supplémentaire sur ce sujet !
Salutations,
Tinghui
@txnelson écrit:
Voici la nouvelle formule ...... c'est la même méthode que la dernière formule, mais il suffit de trouver le point de départ et d'arrivée pour chacun des groupes.
If( Row() == 1,
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
,
:col2 != curCol;
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
);
For( i = Row() + 1, i <= end, i++,
x = x * :col1[i]
);
x;
Voici la nouvelle formule ...... c'est la même méthode que la dernière formule, mais il suffit de trouver le point de départ et d'arrivée pour chacun des groupes.
If( Row() == 1,
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
,
:col2 != curCol;
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
);
For( i = Row() + 1, i <= end, i++,
x = x * :col1[i]
);
x;

Salut Jim @txnelson
Merci pour votre réponse.
Non, mes noms de colonnes ne changent pas. Ils restent comme col1, col2 comme indiqué.Je voudrais ajouter une nouvelle colonne (col3) qui effectue la multiplication vers l'arrière pour une même valeur donnée dans col2. Je démontre mon besoin dans le tableau suivant.S'il te plait peux-tu aider?
col1 col2 col3
1 x 6 (c'est-à-dire 1 x 2 x 3)
2 x 6 (soit 2 x 3)
3 x 3 (soit 3)
2 et 240 (soit 2x4x5x6)
4 et 120 (soit 4 x 5 x 6)
5 et 30 (soit 5 x 6)
6 et 6 (soit 6)
7 z 504 (soit 7x8x9)
8 z 72 (soit 8x9)
9 z 9
Merci!
J'ai supprimé mon message car j'ai raté la variable de regroupement. Mon approche ne fonctionnerait pas dans ce scénario.
Je ne comprends pas vos 3 ensembles de colonnes.Il semble que vous modifiiez les noms de colonne au milieu d'une table de données, ce qui ne fonctionnera pas dans JMP.Ce format de tableau provient-il d'une feuille de calcul Excel ?
Voici une formule simple qui fera ce que vous voulez pour un tableau de données qui ressemble à

J'ai joint le tableau des données.
La formule utilisée est :
x = :col2[Row()];
If( Row() < N Rows( Current Data Table() ),
For( i = Row() + 1, i <= N Rows( Current Data Table() ), i++,
x = x * :col2[i]
)
);
x;
Cette même idée peut être utilisée s'il y a plusieurs endroits dans une table de données qui doivent redémarrer la multiplication.L'identification du moment de redémarrage et du moment de fin devrait simplement être élaborée