cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Try the Materials Informatics Toolkit, which is designed to easily handle SMILES data. This and other helpful add-ins are available in the JMP® Marketplace
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