Choose Language Hide Translation Bar
Highlighted
SrihariGopal
Level II

Simple Question about Loops

Hello,

 

I'm a longtime JMP user, but just recently started learning about scripts. I'm trying to learn the basics, and one of the key things I want to master is the use of for loops.

 

So I created a sample dataset with 4 columns:

1) PATIENTID: list of unique values for patient number
2) VALUE: Value of a patient rating at a particular timepoint
3) TIME: Timepoint at which patient rating was collected
4) PARAM: The patient rating is divided into 4 items and a total score

 

I wrote a script to iterate through all of the rows in this data table and to evaluate the values of two different variables (:TIME and :VALUE). If the condition is met, I'd like to add a character value to a row in a new column which is either Yes or No.

 

Here is the script that I wrote. JMP returns empty values for each of the rows in the new column:

 

Names Default To Here( 1 );
dt = current data table ();
tr = N Rows (dt);
dt << New Column ("TEST", "CHARACTER", 
For (i = 1, i <= tr, i++,
	If( 
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	)
				)
	;

This is a simple script, and once I understand the mechanics, would like to add more conditions. But am stuck at this point because the script is not working properly.

 

I also tried writing this script using the For Each Row function, but still am having the same problem.

 

Any advice on what I'm doing wrong? Sorry if this is a simple answer, I looked through the documentation and can't seem to figure out what I'm doing wrong.

1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
MathStatChem
Level VI

Re: Simple Question about Loops

The task you are wanting to do can be accomplished in two ways:

 

a) use a Formula property for the column:

Names Default To Here( 1 );
dt = current data table ();
tr = N Rows (dt);
dt << New Column ("TEST", "CHARACTER", 
Formula(
	If( 
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	)
				)
	;

b)  iterate with a loop

Names Default To Here( 1 );
dt = current data table ();

dt << New Column ("TEST", "CHARACTER", Character, Nominal);
for(ii=1, ii<=N Rows(dt), ii++, 
:test[ii]=If( 
		(:TIME[ii] == "BASELINE" & :VALUE[ii] > 3)
		,"YES"
		,"NO"
		)
	);

you can also use For Each Row()

Names Default To Here( 1 );
dt = current data table ();

dt << New Column ("TEST", "CHARACTER", Character, Nominal);
for each row( 
:test=If( 
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	);

 

View solution in original post

5 REPLIES 5
Highlighted
SrihariGopal
Level II

Re: Simple Question about Loops

Here is a similar script that I wrote to accomplish the same task, but instead using the For Each Row function. This doesn't work either.

Names Default To Here( 1 );
dt = current data table ();
dt << New Column ("TEST", "CHARACTER", 
For Each Row (dt, 
	If (
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	)
				)
	;

Any help appreciated

 

Highlighted
SrihariGopal
Level II

Re: Simple Question about Loops

One more question:
The JSL documentation says that the for loops are incremented using the 3rd argument in the For function. I've seen this typically written as i++. I assume this means to increment i in place by 1. But what do I do if I want to increment by values less than 1? How do I write the argument?

The JSL documentation and the scripting index tool don't make any mention of how to do this.

Thanks
Highlighted
ms
Super User ms
Super User

Re: Simple Question about Loops

Loops are usually used for iterating through table rows or over items in a list, hence an increment by one is most common. However, the third argument must not be i++. It could be anything that makes sense.

 

A few examples:


For(i = 1, i <= 10, i = i + 0.1, Expr()); // Increment < 1 (100 iterations)

For(i = 10, i > 1, i--, Expr()); // Loop "backwards"

For(x = 2, x <= 10, x = 2, Expr()); // Eternal loop (better avoid these)

 

Highlighted
MathStatChem
Level VI

Re: Simple Question about Loops

The task you are wanting to do can be accomplished in two ways:

 

a) use a Formula property for the column:

Names Default To Here( 1 );
dt = current data table ();
tr = N Rows (dt);
dt << New Column ("TEST", "CHARACTER", 
Formula(
	If( 
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	)
				)
	;

b)  iterate with a loop

Names Default To Here( 1 );
dt = current data table ();

dt << New Column ("TEST", "CHARACTER", Character, Nominal);
for(ii=1, ii<=N Rows(dt), ii++, 
:test[ii]=If( 
		(:TIME[ii] == "BASELINE" & :VALUE[ii] > 3)
		,"YES"
		,"NO"
		)
	);

you can also use For Each Row()

Names Default To Here( 1 );
dt = current data table ();

dt << New Column ("TEST", "CHARACTER", Character, Nominal);
for each row( 
:test=If( 
		(:TIME == "BASELINE" & :VALUE > 3)
		,"YES"
		,"NO"
		)
	);

 

View solution in original post

Highlighted
ms
Super User ms
Super User

Re: Simple Question about Loops

It does not work because the loop is placed inside the New Column definition. Either create the column and fill its values in separate statements, or use a column formula.

 

Look at these three jsl examples that should give identical result:

Names Default To Here(1);
dt = Current Data Table();
tr = N Rows(dt);

//1. Fill values with a For() loop
dt << New Column("TEST", "CHARACTER");
For(i = 1, i <= tr, i++,
    :TEST[i] = If(:TIME[i] == "BASELINE" & :VALUE[i] > 3,
        "YES",
        "NO"
    )
);

//2. Fill with For Each Row()

dt << New Column("TEST2", "CHARACTER");
For Each Row(:TEST2 = If(:TIME == "BASELINE" & :VALUE > 3, "YES", "NO"));

//3. Use a column formula in TEST3
dt << New Column("TEST3",
    "CHARACTER",
    Formula(If(:TIME == "BASELINE" & :VALUE > 3, "YES", "NO"))
);

 

 

Article Labels

    There are no labels assigned to this post.