Creazione di formule di tabelle dati runtime con JSLMi imbatto in questo problema di tanto in tanto e non ho trovato una soluzione che mi soddisfi, quindi mi chiedo cosa abbiano fatto gli altri. Supponiamo che il nome della colonna e i valori aggiuntivi della formula non siano noti fino al runtime. Come semplice esempio, supponiamo di voler creare una formula che moltiplichi una colonna per un valore fornito dall'utente.
Questo non funziona:
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)
));
Nemmeno questo:
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)
));
anche se sembrano funzionare se vai nella formula (finché non clicchi Valuta). Mi sfugge qualcosa? Ho usato questo approccio
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)
));
Ma non mi piace dover usare Riga() per ottenere una valutazione corretta della formula. Il comportamento nei primi due script è un bug?
Re: Creazione di formule di tabelle dati runtime con JSLFunzionerebbe qualcosa del genere? Non usa la funzione row(), ma non lo fa nemmeno esattamente come stai cercando di fare. L'ho rubato da questa pagina (che ho aggiunto ai preferiti per quando ho bisogno di fare lavoro di tipo 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 );Re: Creazione di formule di tabelle dati runtime con JSLGrazie Jed,
Questo è utile, così come il link. Avrei dovuto essere più chiaro nella descrizione del problema. La valutazione della formula non può essere parte della funzione. Ho intenzione di usare l'espressione della formula in altre parti del codice, quindi non voglio che venga valutata immediatamente.
Re: Creazione di formule di tabelle dati runtime con JSLEcco un estratto di un po' di codice che ho scritto per Chris. Devo creare una formula da altre formule e assicurarmi che supporti il Profiler. Utilizzare un indice vuoto sui riferimenti ha aiutato ma ha causato altri problemi. Non sono sicuro di cosa vuoi fare, ma spero che questo frammento fornisca delle buone idee che puoi usare.
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
)
);
);Re: Creazione di formule di tabelle dati runtime con JSLSembra che io abbia seguito un percorso simile a quello di Mark. Puoi costruire la formula come una stringa e poi eval insert() ed eval( parse() ) quando sei pronto per applicarla alla colonna. Funzionerebbe per il tuo script?
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 ) );Re: Creazione di formule di tabelle dati runtime con JSLAnni fa, quando parlavo con @JosephMorgan di questo genere di cose, lui sconsigliò fortemente l'uso della concatenazione o sostituzione di stringhe e indicò che tutto poteva essere realizzato tramite la gestione delle espressioni, fatta eccezione per una cosa che non ricordo e che potrebbe non essere più un problema. L'uso delle stringhe rende il codice molto più difficile da leggere e gestire. Ci sono probabilmente altre ragioni più fondamentali, ma non ricordo.
A quanto pare, esiste una soluzione semplice che utilizza la funzione Come ambito() (grazie a @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 />