使用 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 建立運行時資料表公式這是我為克里斯編寫的一些程式碼的摘錄。我必須從其他公式建立一個公式,並確保它支援 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 建立運行時資料表公式看來我走了一條和馬克類似的路。您可以將公式建構成字串,然後在準備應用到列時使用 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 />