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.
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"
)
);
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
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)
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"
)
);
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"))
);