cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Discussions

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

Nested If statements

Hi, I'm getting lost in implementing nested If statements in JSL:

 

dt1:Run Validity <<
Set Formula(
	If( (:Sample Name == "NTC" & (:Target Name == "MIX 1 A" | :Target Name == "MIX 2 B" | :Target Name == "MIX 2 C" | :Target Name == "MIX 2 D" | :Target Name == "MIX 3 F" |
		 :Target Name == "MIX 3 G" | :Target Name == "MIX 3 H" | :Target Name == "MIX 4 I" | :Target Name == "MIX 4 J")), If( (:CT == "Undetermined"), "Pass", "Fail")),

	If( (:Sample Name == "PC" & :Target Name == "MIX 1 A"), If( (1 < :CT_numeric < 5), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 2 B"), If( (3 < :CT_numeric < 4), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 2 C"), If( (2 < :CT_numeric < 5), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 2 D"), If( (1 < :CT_numeric < 4), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 3 E"), If( (1 < :CT_numeric < 3), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 3 F"), If( (4 < :CT_numeric < 5), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 3 G"), If( (3 < :CT_numeric < 6), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 4 H"), If( (1 < :CT_numeric < 4), "Pass", "Fail")),
	If(	(:Sample Name == "PC" & :Target Name == "MIX 4 I"), If( (2 < :CT_numeric < 5), "Pass", "Fail")),
		
	If(	(:Sample Name != "PC" & (:Target Name == "MIX 1 IC" |:Target Name == "MIX 2 IC" | :Target Name == "MIX 3 IC" | :Target Name == "MIX 4 IC")), If((1 < :CT_numeric < 4), "Pass", "Fail"))

	);

Essentially I want for rows with sample name = NTC and Target Name one of Mix 1 A, Mix 1 B... if CT is undetermined return pass, if not fail

 

Is there a better way to do this with if statements? Or could you point out where I'm going wrong?

 

Thank you

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: Nested If statements

I would suggest using Contains() instead of long copy pasted list of or statements and possible associative array for value comparison. If you need a formula you might have to use Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute to get lists / associative arrays into the formula. This might give some ideas:

Names Default To Here(1);

aa_pc_limits = Associative Array();
aa_pc_limits["MIX 1 A"] = {1, 5};
aa_pc_limits["MIX 2 B"] = {3, 4};
aa_pc_limits["MIX 2 C"] = {2, 5};
aa_pc_limits["MIX 2 D"] = {1, 4};

ntc_valid = {"MTX 1 A", "MIX 2 B", "MIX 2C"};
non_pc_valid = {"MTX 1 IC", "MIX 2 IC", "MIX 3 IC"};


dt = New Table("Untitled",
	Add Rows(8),
	New Column("Sample Name",
		Character,
		"Nominal",
		Set Values({"NTC", "NTC", "AA", "AA", "AA", "PC", "PC", ""})
	),
	New Column("Target Name",
		Character,
		"Nominal",
		Set Values(
			{"MTX 1 A", "MTX AAAA", "MTX 1 IC", "MTX 1 IC", "AAA", "MIX 1 A", "BBB",
			""}
		)
	),
	New Column("CT_numeric",
		Numeric,
		"Continuous",
		Format("Best", 12),
		Set Values([., ., 2, 5, ., 2, 5, .])
	),
	New Column("CT",
		Character,
		"Nominal",
		Set Values({"Undetermined", "", "", "", "", "", "", ""})
	),
	New Column("Run Validity",
		Character,
		"Nominal",
		Set Values({"", "", "", "", "", "", "", ""})
	)
);

dt:Run Validity << Set Formula(
	If(:Sample Name == "NTC",
		If(Contains(ntc_valid, :Target Name),
			If(:CT == "Undetermined",
				"Pass";
			, // else
				"Fail";
			)
		, // else
			"NOT DEFINED. NTC"
		)
	, :Sample Name != "PC",
		If(Contains(non_pc_valid, :Target Name),
			If((1 < :CT_numeric < 4),
				"Pass"
			,
				"Fail"
			)
		,
			"NOT DEFINED. NON-PC"
		)
	, :Sample Name == "PC",
		If(Contains(aa_pc_limits, :Target Name),
			IfMZ(aa_pc_limits[:Target Name][1] < :CT_numeric < aa_pc_limits[:Target Name][2],
				"PASS"
			,
				"FAIL"
			)
		,
			"NOT DEFINED. PC";
		)
	, //else
		"NOT DEFINED";
	);
);
-Jarmo

View solution in original post

6 REPLIES 6
jthi
Super User

Re: Nested If statements

I would suggest using Contains() instead of long copy pasted list of or statements and possible associative array for value comparison. If you need a formula you might have to use Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute to get lists / associative arrays into the formula. This might give some ideas:

Names Default To Here(1);

aa_pc_limits = Associative Array();
aa_pc_limits["MIX 1 A"] = {1, 5};
aa_pc_limits["MIX 2 B"] = {3, 4};
aa_pc_limits["MIX 2 C"] = {2, 5};
aa_pc_limits["MIX 2 D"] = {1, 4};

ntc_valid = {"MTX 1 A", "MIX 2 B", "MIX 2C"};
non_pc_valid = {"MTX 1 IC", "MIX 2 IC", "MIX 3 IC"};


dt = New Table("Untitled",
	Add Rows(8),
	New Column("Sample Name",
		Character,
		"Nominal",
		Set Values({"NTC", "NTC", "AA", "AA", "AA", "PC", "PC", ""})
	),
	New Column("Target Name",
		Character,
		"Nominal",
		Set Values(
			{"MTX 1 A", "MTX AAAA", "MTX 1 IC", "MTX 1 IC", "AAA", "MIX 1 A", "BBB",
			""}
		)
	),
	New Column("CT_numeric",
		Numeric,
		"Continuous",
		Format("Best", 12),
		Set Values([., ., 2, 5, ., 2, 5, .])
	),
	New Column("CT",
		Character,
		"Nominal",
		Set Values({"Undetermined", "", "", "", "", "", "", ""})
	),
	New Column("Run Validity",
		Character,
		"Nominal",
		Set Values({"", "", "", "", "", "", "", ""})
	)
);

dt:Run Validity << Set Formula(
	If(:Sample Name == "NTC",
		If(Contains(ntc_valid, :Target Name),
			If(:CT == "Undetermined",
				"Pass";
			, // else
				"Fail";
			)
		, // else
			"NOT DEFINED. NTC"
		)
	, :Sample Name != "PC",
		If(Contains(non_pc_valid, :Target Name),
			If((1 < :CT_numeric < 4),
				"Pass"
			,
				"Fail"
			)
		,
			"NOT DEFINED. NON-PC"
		)
	, :Sample Name == "PC",
		If(Contains(aa_pc_limits, :Target Name),
			IfMZ(aa_pc_limits[:Target Name][1] < :CT_numeric < aa_pc_limits[:Target Name][2],
				"PASS"
			,
				"FAIL"
			)
		,
			"NOT DEFINED. PC";
		)
	, //else
		"NOT DEFINED";
	);
);
-Jarmo
Craige_Hales
Super User

Re: Nested If statements

Another possible approach to managing a complicated set of rules

dt = open("$sample_data/big class.jmp");
dt<<newcolumn("Run Validity", formula(
	lookup = asconstant([ // asConstant builds the lookup once
		"F" => [ // rules for females, by age
			12 => if(59<height<63,"Pass","Fail"),
			13 => if(60<height<65,"Pass","Fail"),
			14 => "Fail",
			15 => "Pass",
			 => "Maybe" // rule for other ages
		],
		"M" => [ // rules for males, by age
			12 => if(80<weight<90,"Pass","Fail"),
			13 => if(name=="JOHN","Pass","Fail"),
			 => "Possibly" // rule for other ages
		],
		 => [ => "?"]  // rule for unknown sex
	]);
	// use the table, above, to look up a rule, then evaluate the rule
	Eval( lookup[:sex][:age] )
));

Edit: changed =>"?" to =>[=>"?"] as described below.

Craige
Agustin
Level IV

Re: Nested If statements

Thank you for this, but I'm not sure I follow it fully. What do 12, 13, 14 etc. refer to in this case?

 

Thanks

jthi
Super User

Re: Nested If statements

I would guess they refer to ages (and keys in associative arrays to perform lookup).

-Jarmo
Craige_Hales
Super User

Re: Nested If statements

12,13,14 are the ages of the big class rows.

The [ square brackets ] for the outer associative array define two entries, one for "M" and one for "F". Each of those entries is also a an associative array with several entries indexed by ages. At the bottom you can see a 2-dimensional index using [sex][age] to look up a rule. Associative arrays also have an otherwise value that can be used when the key is not in the array.

So, Lookup["M"] returns an AA with entries for 12 and 13; Lookup["M"][12] returns the 80...90 rule, and evaluating that uses the weight value from the current row to produce a string.

 

The =>"?" needs to be =>[=>"?"] to actually work if there were values other than F and M. Otherwise Lookup["X"] would not return the expected AA for a 2nd index.

Craige
Agustin
Level IV

Re: Nested If statements

Thank you, I was looking for something like contains for ages but couldn't find it. And thank you for the nest if statements, I'll give this a go.

Recommended Articles