cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • JMP 19 is here! See the new features at jmp.com/new.
  • Due to global connectivity issues impacting AWS Services, users may experience unexpected errors while attempting to authorize JMP. Please try again later or contact support@jmp.com to be notified once all issues are resolved.

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
hcarr01
Level VI

Script

Bonjour à tous,
 
Je dispose d’une base de données dans laquelle j’aimerais créer une nouvelle colonne à partir d’une formule ou d’un script.
 
Voici un aperçu de la base de données :
 
hcarr01_1-1689685617209.png

 

- la colonne T représente des opérations à effectuer
- la colonne X_3 représente une particularité
- La colonne op représente des objets
 
Le but est de créer une colonne « bilan » dans laquelle on ajoute « ko » et le numéro correspondant à « op » lorsque la somme des défauts est différente de 0 d’une ligne à une autre pour un même « obj » (ici valeur égale à A).
 
Dernière particularité, la colonne bilan doit être remplie pour la numéro des opérations « 3061 ».
Il s’agit ici d’un aperçu de la base de données, la colonne obj vaut « A » mais dans la base de données cette colonne change de valeur.
 
Merci pour vos réponses !
27 REPLIES 27
jthi
Super User

Re: Script

There is no point adding For Each Row back until you get other parts of the script working. You can continue with the example I did provide until you have correct value set to row 9 (due to working with unique_objects[2] which is B). To get OPE indices which are higher than the  "3061" rows OPE you can use Loc like this.

valid_ope_idx = Loc(opes > opes[input_loc]);

Do note that these are indices within opes matrix NOT rows from the data table. To convert them back rows you can use those indices with object_rows as object_rows is a matrix with rows for the specific unique object

-Jarmo
hcarr01
Level VI

Re: Script

Oui je suis d’accord avec vous !
Les valeurs que je trouve avec ma formule sont correctes et je trouve la même chose que vous.
 
 
hcarr01_0-1690204578841.png
 
Cependant c’est dans la construction de la suite du script où j’ai plus de mal !
 
Car je dois retourner les valeurs « ko-..... / ko-... » lorsque :OPE est supérieure à :OPE correspondante à :T = 3061 et lorsque la :SOMME DEFAUT est différente de 0 (comme dans l’exemple).
 
jthi
Super User

Re: Script

Them you continue with similar idea

  1. Add check that there are more than 0 items in valid_ope_idx
  2. Get all values for valid_ope_idx
  3. Then from this get the indices of values which are larger than 0
  4. And then with this you can finally get the values from :op for these specific indices (remember to convert them to rows first)
  5. Concatenate these values together using Concat Items()
  6. Add value to correct row
-Jarmo
hcarr01
Level VI

Re: Script

Dans ma base de données de test cela marche correctement avec le code suivant :

Names Default To Here(1);

dt = current data table();
dt << New Column("BILAN", Character, Nominal);


Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];


somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
	Starts With( col_name, "SOMME" )
);



dt = current data table();
For Each({unique_objects}, unique_objects,
	object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
	b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
	show(b);
	input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
	z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
	value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
	show(value_OPE_3061); 

	valid_ope_idx = Loc(b > value_OPE_3061 & dt[object_rows,somme_col] > 0) ;
	show(valid_ope_idx); 
	
	if( N items(valid_ope_idx) < 1,
		continue();
	,
		ops = dt[object_rows[valid_ope_idx], "op"];
		result_str = "ko - " || Concat Items(ops, " / ko - ");
		dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
	);

);
Cependant, dans ma base de données finale, il est possible que pour un même obj plusieurs fois la valeur :T = 3061 est affichée (par contre les valeurs de OPE sont les mêmes !).
Je pense qu’il faut donc modifier encore quelque chose, il faut que la valeur de valeur_OPE_3061 soit unique (et pas par exemple value_OPE_3061 = [ 50 , 50 , 50 ] mais plutôt value_OPE_3061 = [ 50 ]).
Existe-t-il une fonction sur JMP permettant de supprimer les doublons d’une matrice/liste ?
 
Merci pour vos réponses !
jthi
Super User

Re: Script

I thought earlier you said that it is impossible that there would be multiple "3061" values?

 

One option to remove duplicates is to use Associative Array() with << get keys (doesn't work if you have floats),  other good in this case would be to use Design(<<levels).

-Jarmo
hcarr01
Level VI

Re: Script

J'ai rajouté cette partie cela fonctionne encore mieux :

 

Names Default To Here(1);

dt = current data table();
dt << New Column("BILAN", Character, Nominal);


Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];


somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
	Starts With( col_name, "SOMME" )
);



dt = current data table();
For Each({unique_objects}, unique_objects,
	object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
	b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
	show(b);
	input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
	
	if( N items(input_loc) < 1,
		continue();
	,
	
		z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
		value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
		
		liste={}; // transformer en liste pour supprimer les doublons
		for (i = 1, i <= NRows(value_OPE_3061), i++,
			for (j = 1, j <= NCols(value_OPE_3061), j++,
				InsertInto(liste, value_OPE_3061[i, j]);
			);
		);
		
		// supprimer les doublons
		if( N items(liste) <= 1, 
			a = liste;
		,
			a = Left(liste,1);
		);
		
		// repasser en matrice pour faire les comparaisons
		Mat_3061 = Matrix(a);
		show(Mat_3061);
		

		valid_ope_idx = Loc(b > Mat_3061 & dt[object_rows,somme_col] > 0) ;
		show(valid_ope_idx); 
		
	
		if( N items(valid_ope_idx) < 1,
			continue();
		,
			ops = dt[object_rows[valid_ope_idx], "op"];
			result_str = "ko - " || Concat Items(ops, " / ko - ");
			dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
		);

);
);

Effectivement vous avez raison @jthi, mais je parlais que pour une valeur 3061 d'un :obj il ne peut pas y avoir différentes valeurs de la variable :OPE (après dans un obj il peut y avoir 2 fois par exemple la valeur :T égale à 3061 mais la valeur :OPE sera la même).

 

Au final, en sortie, j'aimerais que l'affichage ne se répète pas lorsqu'il y a plusieurs fois la valeur :T égale à 3061 pour un même :obj.

 

Exemple : 

 

hcarr01_0-1690276418497.png

 

Avec un script comme celui-ci :

input_loc = Loc(dt[object_rows, "T"], "3061");// localiser 3061 pour chaque objet
	
	liste2={}; // transformer en liste pour supprimer les doublons
		for (i = 1, i <= NRows(input_loc), i++,
			for (j = 1, j <= NCols(input_loc), j++,
				InsertInto(liste2, input_loc[i, j]);
			);
		);
		
		// supprimer les doublons
		if( N items(liste2) <= 1, 
			c = liste2;
		,
			c = Left(liste2,1);
		);
		
		// repasser en matrice pour faire les comparaisons
		loc_3061 = Matrix(c);
		

Cela fonctionne correctement, je prends le premier indice correspondant à :T égale à 3061.

 

Mais comme sur la capture ci-dessus, j'aimerais pouvoir enlever les éléments en double sur la même ligne :

ko - 2203 / ko - 2203 --> ko - 2203

 

 

jthi
Super User

Re: Script

You could just pick the first index which has 3061 value for the object.

-Jarmo
jthi
Super User

Re: Script

Something like this is how I would have solved this. Should work with the example data

Names Default To Here(1);

// dt = Open("$DOWNLOADS/AAA.jmp");
// dt = Current Data Table();

dt = New Table("AAA(1)",
	Add Rows(12),
	Compress File When Saved(1),
	New Column("obj", Character(16), "Nominal", Set Values({"A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "C", "C"})),
	New Column("T",	Character(4), "Ordinal", Set Values({"3052", "3061", "3082", "3940", "4012", "5010", "2890", "4060", "3061", "3061", "3081", "5010", "3061"})),
	New Column("OPE", Numeric, "Continuous", Format("Best", 12), Set Values([12, 20, 32, 44, 56, 125, 210, 54, 60, 60, 80, 45, 50])),
	New Column("X__3", Character(4), "Nominal", Set Values({"rien", "rien", "incl", "ret", "ret", "rien", "incl", "incl", "ret", "ret", "incl", "ret", "rien"})),
	New Column("SOMME DEFAUT", Numeric, "Continuous", Format("Best", 12), Set Values([0, 0, 1, 2, 1, 0, 2, 1, 2, 2, 1, 1, 0])),
	New Column("op", Character(12), "Nominal", Set Values({"40", "32", "55", "212", "510", "180", "2100", "2240", "2100", "2100", "500", "", ""}))
);

dt << New Column("bilan", Character, Nominal);

Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];

For Each({unique_object}, unique_objects,
	object_rows = Loc(m_obs, unique_object);
	input_loc = Loc(dt[object_rows, "T"], "3061");
	
	If(N Items(input_loc) == 0,
		continue();
		//Throw("3061 not found");
	, N Items(input_loc) > 0,
		input_loc = input_loc[1];
	);
	
	opes = dt[object_rows, "OPE"];
	valid_ope_idx = Loc(opes > opes[input_loc]);

	If(N Items(valid_ope_idx) < 1,
		result_str = ".";
	,
		values = dt[object_rows[valid_ope_idx], "SOMME DEFAUT"];
		ops = dt[object_rows[valid_ope_idx[Loc(values)]], "op"];
		result_str = "ko - " || Concat Items(ops, " / ko - ");
	);
	
	dt[object_rows[input_loc], "bilan"] = result_str;
);

 

-Jarmo

Recommended Articles