Erstellen von Laufzeit-Datentabellenformeln mit JSLIch stoße immer wieder auf dieses Problem und habe noch keine Lösung gefunden, mit der ich zufrieden bin. Daher frage ich mich, was andere Leute getan haben. Angenommen, der Spaltenname und zusätzliche Formelwerte sind erst zur Laufzeit bekannt. Nehmen wir als einfaches Beispiel an, ich möchte eine Formel erstellen, die eine Spalte mit einem vom Benutzer bereitgestellten Wert multipliziert.
Das funktioniert nicht:
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)
));
Das hier auch nicht:
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)
));
obwohl es zu funktionieren scheint, wenn Sie in die Formel gehen (bis Sie auf „Auswerten“ klicken). Übersehe ich etwas? Ich verwende diesen Ansatz
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)
));
Aber ich möchte nicht Reihe() verwenden müssen, damit die Formel richtig ausgewertet wird. Ist das Verhalten in den ersten beiden Skripten ein Fehler?
Betreff: Erstellen von Laufzeit-Datentabellenformeln mit JSLWürde so etwas funktionieren? Es verwendet nicht die Funktion row(), erreicht dies aber auch nicht genau so, wie Sie es versuchen. Ich habe es von dieser Seite geklaut (die ich als Lesezeichen gespeichert habe, wenn ich Arbeiten vom Typ eval/expr durchführen muss).
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 );Betreff: Erstellen von Laufzeit-Datentabellenformeln mit JSLDanke, Jed,
Das ist hilfreich, ebenso wie der Link. Ich hätte das Problem klarer beschreiben sollen. Die Formelauswertung kann nicht Teil der Funktion sein. Ich habe vor, den Formelausdruck in anderen Teilen des Codes zu verwenden, daher möchte ich nicht, dass er sofort ausgewertet wird.
Betreff: Erstellen von Laufzeit-Datentabellenformeln mit JSLHier ist ein Auszug aus einem Code, den ich für Chris geschrieben habe. Ich muss eine Formel aus anderen Formeln erstellen und sicherstellen, dass sie den Profiler unterstützt. Die Verwendung eines leeren Indexes bei Referenzen hat geholfen, verursachte aber andere Probleme. Ich bin nicht sicher, was Sie tun möchten, aber ich hoffe, dieser Codeausschnitt bietet einige gute Ideen, die Sie verwenden können.
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
)
);
);Betreff: Erstellen von Laufzeit-Datentabellenformeln mit JSLSieht so aus, als hätte ich einen ähnlichen Weg wie Mark eingeschlagen. Sie können die Formel als Zeichenfolge konstruieren und dann insert() und eval( parse() ) ausführen, wenn Sie bereit sind, sie auf die Spalte anzuwenden. Würde das für Ihr Skript funktionieren?
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 ) );Betreff: Erstellen von Laufzeit-Datentabellenformeln mit JSLAls ich vor Jahren mit @JosephMorgan über diese Art von Dingen sprach, riet er dringend von der Verwendung von Zeichenfolgenverkettung oder -ersetzung ab und gab an, dass alles durch Ausdrucksverarbeitung erreicht werden könne, mit Ausnahme einer Sache, an die ich mich nicht erinnere und die möglicherweise kein Problem mehr darstellt. Die Verwendung von Zeichenfolgen macht den Code viel schwieriger zu lesen und zu warten. Es gibt wahrscheinlich andere, grundlegendere Gründe, aber ich kann mich nicht erinnern.
Wie sich herausstellt, gibt es eine einfache Lösung mit der Funktion Als Scoped() (danke an @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 />