I'm having a conceptual problem figuring out how local variables work. I'll simplify the issue to focus in on what is confusing to me.
I create a local variable, say t0, with a value of 5. Then I write a column formula to increment this value by 1... either t0=t0+1 or t0+=1 (it doesn't seem to matter), the result that I expected was that when JMP evaluated each cell in the column, it would increment the variable so I'd get 6, 7, 8, etc as I moved down the column. Instead, I get a column of 6's. So the formula is not incrementing the variable.
Can someone explain to me what I'm not understanding about how JMP handles local variables? Also, since my approach doesn't work is there another way to increment a variable? I can do it with Lag but that seems needlessly complex for something so simple.
Also, I'm not clear on the distinction between local variables, table variables, and parameters.
Thanks in advance for all help provided.
You might be interested in the Row()
function inside of a column formula -- it returns the current row that the formula is being run against. As for variables and scoping -- it is usually best to be explicit about variable scopes. Thus to use a global counter, do ::t0 += 1
-- the double colon explicitly scopes the name to the global namespace. If you want a local name, explicitly scope it, i.e., local:t0
There is also the Here
namespace, and again it is best to be explicit in scoping. I recommend being explicit as JMP is buggy and will not always adhere to the stated scoping rules.
I guess that you wrote something like the following as a column formula:
Local({t0 = 5}, t0 = t0 + 1)
And you expect that the initial assignment
t0 = 5
only occurs once when the data table evaluate a column, cell by cell from top to bottom.
You have seen that is not happening. What you see is the assignment occurs every time when a cell is evaluated. If you have SAS programming experience, you might be looking for something similar to RETAIN statement in SAS. I am not aware of such thing exists in JMP's scripting language.
But I had the similar need to do calculations that need to retrieve results in previous calculations.
If the result is intermediate and temporary, I will store the result in a separate column. If the result is just a value in previous cell in the same column, I will just refer to the previous cell. Either way, you may need to use the Row() function that @ErraticAttack mentioned.
I attach an example to illustrate.
When you want to have incrementing value in a formula you usually have three options:
Names Default To Here(1);
dt = New Table("",
Add Rows(10)
);
dt << delete column(1);
dt << New Column("AsConstant", Numeric, Continuous, Formula(
As Constant(myvar = 4); // one less than the value you want on first row
myvar = myvar + 1;
));
dt << New Column("Row()", Numeric, Continuous, Formula(
Row() + 4;
));
dt << New Column("IfFirstRow", Numeric, Continuous, Formula(
If(Row() == 1,
myvar2 = 4;
);
myvar2 = myvar2 + 1;
));
Rest of this post gets a bit messy
What can happen, is that your variables "escape" to other formulas if you aren't careful
Names Default To Here(1);
dt = New Table("",
Add Rows(10)
);
dt << delete column(1);
col1 = dt << New Column("AsConstant", Numeric, Continuous, Formula(
As Constant(myvar = 4); // one less than the value you want on first row
myvar = myvar + 1;
));
col2 = dt << New Column("AsConstant", Numeric, Continuous, Formula(
myvar;
));
dt << New Column("AsConstant", Numeric, Continuous, Formula(
myvar = 10;
));
dt << New Column("AsConstant", Numeric, Continuous, Formula(
myvar;
));
// Observe the values for column 2
wait(2);
dt << add rows(1);
wait(2);
col1 << Suppress Eval(1);
wait(2);
dt << add rows(1);
More general
There are two types of variables in JMP: global and local. What local means is determined by the scope which defines it. Scripting Guide > JSL Building Blocks > Global and Local Variables. You can read regarding variables, scope and namespace from Scripting Guide from JMP Help web page. Note that not all of them can be easily applied to formulas and are specific scripting.
Documentation regarding formulas seems to have some "fun" with local variable. There is Local Variable, then there is Temporary Variable (which seems to be same as local variable, you just create it with a funny button? Shouldn't the button be Make Local Variable and not Make Temporary Variable?) and finally there is parameter, special type of local variable (no idea what parameter means in this case).
Using JMP > Create Formulas in JMP > Use Local Variables in Formulas
Names Default To Here(1);
dt = New Table("",
Add Rows(10)
);
dt << delete column(1);
// Messing with Local({})
dt << New Column("Local1", Numeric, Continuous, Formula(
Local({myvar3 = 4}, // "Constant as we redefine it every time"
myvar3 = myvar3 + 1
);
));
dt << New Column("Local2", Numeric, Continuous, Formula(
Local({myvar4},
myvar4 = 4;
myvar4 = myvar4 + 1
);
));
dt << New Column("Local3", Numeric, Continuous, Formula(
Local({myvar5},
If(Row() == 1,
myvar5 = 4;
);
myvar5 = myvar5 + 1;
);
));
dt << New Column("Local4", Numeric, Continuous, Formula(
Local({myvar6},
As Constant(myvar6 = 4);
myvar6 = myvar6 + 1;
);
));
This is excellent guidance. Thanks to all of you.