使用 JSL 构建运行时数据表公式我时不时会遇到这个问题,但一直没有找到满意的解决方案,所以我想知道其他人做了什么。假设列名和其他公式值直到运行时才知道。举一个简单的例子,假设我想创建一个将列乘以用户提供的值的公式。
这不起作用:
buildFormula = Function({tblRef,colName,mult},
exprOut = Substitute(
Expr(col*mult),
Expr(col),Column(tblRef,colName),
Expr(mult),mult
);
Name Expr(exprOut);
);
outExpr = buildFormula(tbl,"Minimum Price ($1000)",3);
Eval(Substitute(
Expr(tbl << New Column("New Formula Column",Formula(form))),
Expr(form),Name Expr(outExpr)
));
以下情况同样如此:
tbl = Open("$sample_data/cars 1993.JMP");
buildFormula = Function({colRef,mult},
exprOut = Substitute(
Expr(col*mult),
Expr(col),colRef,
Expr(mult),mult
);
Name Expr(exprOut);
);
outExpr = buildFormula(Column(tbl,"Minimum Price ($1000)"),Name Expr(fExpr));
Eval(Substitute(
Expr(tbl << New Column("New Formula Column",Formula(form))),
Expr(form),Name Expr(outExpr)
));
尽管如果你进入公式,它似乎有效(直到你点击“评估”)。我是不是漏掉了什么?我一直在使用这种方法
tbl = Open("$sample_data/cars 1993.JMP");
buildFormula = Function({colRef,mult},
exprOut = Substitute(
Expr(col[Row()]*mult),
Expr(col),colRef,
Expr(mult),mult
);
Name Expr(exprOut);
);
outExpr = buildFormula(Column(tbl,"Minimum Price ($1000)"),3);
Eval(Substitute(
Expr(tbl << New Column("New Formula Column",Formula(form))),
Expr(form),Name Expr(outExpr)
));
但不喜欢必须使用排()才能正确计算公式。前两个脚本中的行为是错误吗?
回复:使用 JSL 构建运行时数据表公式类似这样的方法可行吗?它不使用 row() 函数,但也不能完全按照您尝试的方式完成此操作。我从此页面偷了它(我已将其加入书签,以便每次需要执行 eval/expr 类型的工作时使用)。
tbl = Open( "$sample_data/cars 1993.JMP" );
buildFormula = Function( {colRef, mult},
Eval(
Eval Expr(
tbl << New Column( "New Formula Column", Formula( as column (expr (colRef)) * expr (num(mult)) ) )
)
)
);
outExpr = buildFormula( Column( tbl, "Minimum Price ($1000)" ), 3 );回复:使用 JSL 构建运行时数据表公式谢谢杰德,
这很有帮助,链接也是如此。我应该更清楚地描述问题。公式评估不能成为函数的一部分。我计划在代码的其他部分使用公式表达式,所以我不想让它立即评估。
回复:使用 JSL 构建运行时数据表公式这是我为 Chris 编写的一些代码的摘录。我必须从其他公式构建一个公式,并确保它支持 Profiler。在引用上使用空下标有帮助,但会导致其他问题。我不确定你想做什么,但我希望这个代码片段能为你提供一些好的想法。
For( r = 1, r <= nResponses, r++,
// convert a column reference to a column name for substitution
Col Ref to Name = Function( {colref, qualified? = 0 },
If( qualified?,
Parse(Eval Insert("^colref << Get Data Table^:\!"^colref << Get Name^\!"n")),
Parse(Eval Insert(":\!"^colref << Get Name^\!"n"))
)
);
// create expected improvement column formula
limits = Column( dt, y col[r] ) << Get Property( "Response Limits" );
goal[r] = Char( limits["Goal"] );
Match( goal[r],
"Maximize", // apply standard EI formula
Eval(
Substitute(
Expr(
ei = dt << New Column( y col[r] || " Expected Improvement", "Numeric", "Continuous",
Formula(
(:pppfff - yyy) * Normal Distribution( (:pppfff - yyy) / Sqrt( :vvvfff ))
+ Sqrt( :vvvfff ) * Normal Density( (:pppfff - yyy) / Sqrt( :vvvfff ) )
)
)
),
Expr( vvvfff ), Col Ref To Name(vf),
Expr( pppfff ), Col Ref To Name(pf),
Expr( yyy ), refY[r] = predOptY[r]
)
),
"Minimize", // negate standard EI formula
Eval(
Substitute(
Expr(
ei = dt << New Column( y col[r] || " Expected Improvement", "Numeric", "Continuous",
Formula(
(yyy - :pppfff) * Normal Distribution( (yyy - :pppfff) / Sqrt( :vvvfff ))
+ Sqrt( :vvvfff ) * Normal Density( (yyy - :pppfff) / Sqrt( :vvvfff ) )
) )
),
Expr( vvvfff ), Col Ref To Name(vf),
Expr( pppfff ), Col Ref To Name(pf),
Expr( yyy ), refY[r] = predOptY[r]
)
),
"Match Target", // apply joint EI formula
Eval(
Substitute(
Expr(
ei = dt << New Column( y col[r] || " Expected Improvement", "Numeric", "Continuous",
Formula(
deltaMin = Abs( ttt - yyy );
deltaMin * (Normal Distribution( (deltaMin + ttt - :pppfff) / Sqrt( :vvvfff ) )
- Normal Distribution( (-deltaMin + ttt - :pppfff) / Sqrt( :vvvfff ) )
)
+ Sqrt( :vvvfff ) * (
Normal Density( (deltaMin + ttt - :pppfff) / Sqrt( :vvvfff ) )
+ Normal Density( (-deltaMin + ttt - :pppfff) / Sqrt( :vvvfff ) )
- 2 * Normal Density( ttt - :pppfff) / Sqrt( :vvvfff )
)
- (:pppfff - ttt) * (
(Normal Distribution( (deltaMin + ttt - :pppfff)) / Sqrt( :vvvfff ) )
+ Normal Distribution( (-deltaMin + ttt - :pppfff) / Sqrt( :vvvfff ) )
- 2 * Normal Distribution( (ttt - :pppfff) / Sqrt( :vvvfff ) )
)
)
)
),
Expr( vvvfff ), Col Ref To Name(vf),
Expr( pppfff ), Col Ref To Name(pf),
Expr( ttt ),
target[r] = If( Contains( Char( limits ), "Middle" ),
limits["Middle"],
(limits["Lower"] + limits["Upper"]) / 2
),
Expr( yyy ),
/*
yDiff = (Column( dt, y col ) << Get as Matrix) - target[r];
pDiff = (pf << Get As Matrix) - target[r];
refY[r] = If( Min( Abs( yDiff ) ) < Min( Abs( pDiff ) ),
Column( dt, y col )[Loc Min( Abs( yDiff ) )],
pf[Loc Min( Abs( pDiff ) )]
)
*/
predOptY[r]
)
),
"None", // unexpected condition
Throw( "Disallowed: response with Goal of None" ),
// unexpected condition
gp << Close Window;
dt << Delete Columns( { pf, vf } );
Throw( "Disallowed: No response goal found. Response Limits column property is missing" )
);
ei << Set Property( "Response Limits", {Goal( Maximize ), Importance( 1 ), Show Limits( 0 )} )
<< Hide( 1 );
Wait( 0 );
Eval(
Substitute(
Expr(
Insert Into( utilityCols, eee, iii );
),
Expr( eee ), Eval( ei ),
Expr( iii ), 3*(r-1) + 1
)
);
);回复:使用 JSL 构建运行时数据表公式看起来我和 Mark 走了一条类似的路。您可以将公式构造为字符串,然后在准备应用于列时执行 eval insert() 和 eval( parse() )。这对您的脚本有用吗?
tbl = Open("$sample_data/cars 1993.JMP");
colName = "Minimum Price ($1000)";
mult = 3;
formulaString = ":\!"^colName^\!"n * ^mult^";
formula = eval insert( formulaString );
newColumnString = "^tbl^ << new column( \!"New Formula\!", formula( ^formula^ ) )";
newColumn = eval insert( newColumnString );
eval( parse( newColumn ) );回复:使用 JSL 构建运行时数据表公式几年前,当我与@JosephMorgan谈论这类事情时,他强烈反对使用字符串连接或替换,并指出一切都可以通过表达式处理来实现,但有一件事我不记得了,可能不再是问题。使用字符串会使代码更难阅读和维护。可能还有其他更根本的原因,但我记不清了。
事实证明,有一个简单的解决方案,使用与 Scoped() 一样函数(感谢@brady_brady )
</CODE></PRE>
<PRE><CODE class=" language-jsl">tbl = Open("$sample_data/cars 1993.JMP");
buildFormula = Function({colRef,mult},
exprOut = Substitute(
Expr(col*mult),
Expr(col),Name Expr(As Scoped(colRef)),
Expr(mult),mult
);
Name Expr(exprOut);
);
outExpr = buildFormula(Column(tbl,"Minimum Price ($1000)"),3);
Eval(Substitute(
Expr(tbl << New Column("New Formula Column",Formula(form))),
Expr(form),Name Expr(outExpr)
));<BR />