cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • New to JMP? Join us Sept. 23-24 for the Early User Edition of Discovery Summit, tailor-made for new users. Register now for free!
  • Use World Cup data to build models, explore spatial relationships, and create informative visualizations in JMP. Register. July 17, 2 pm US Eastern Time.
  • Your voice matters! Tell us how you prefer to receive JMP updates, so we can tailor our communication to your needs. Take short survey.

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