EIN Frage aus uandw über Spaltenformeln hat diesen Beitrag gestartet. Wenn Sie den Formeleditor nur zum Erstellen von Spaltenformeln verwenden, können Sie fast alles ignorieren. In diesem Beitrag geht es um die Verwendung von JSL zum Erstellen einer Spaltenformel.
Zuerst ein wenig über den Formula-Befehl. Hier ist eine ganz einfache:
The formula for column C adds columns A and BDie Formel für Spalte C fügt die Spalten A und B hinzu
Das Tabellenskript (Dreieck oben links -> Tabellenskript kopieren, in einen Editor einfügen) sieht so aus:
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( :a + :p</img> )
)
)
Zeile 5 legt die Formel fest; Die Formel ist ein Ausdruck, der die Spalten a und b hinzufügt. Der Ausdruck läuft erst viel später. Der Ausdruck wird als Ausdruck als Teil der Spalte gespeichert. Wenn der Tabelle eine weitere Zeile hinzugefügt oder die Werte in Spalte a oder b geändert werden, kann der Ausdruck erneut ausgewertet werden, um einen Wert für Spalte c zu erhalten.
Dies ist sowohl freundliches als auch ungewöhnliches Verhalten. Ungewöhnlich, weil die meisten Funktionen ihre Argumente auswerten: sqrt( 4 + 5 ) gibt 3 zurück. Freundlich, weil Sie fast nie möchten, dass JMP die Formel einer Spalte auswertet, bevor sie der Spalte zugewiesen wurde.
Manchmal kann ein Formelausdruck wirklich kompliziert sein. So kompliziert, dass es einfacher wäre, ein Programm zu schreiben, um den Ausdruck zu schreiben. Um dies im Formelbefehl zu tun, müssten Sie dem Formelbefehl mitteilen, dass er das Argument vorab auswerten und den resultierenden Ausdruck als Formel verwenden soll. Dazu fügen Sie einen eval( )-Wrapper um den Code hinzu, um ihn vorab auszuwerten. Wenn der Formelbefehl „eval“ um den Ausdruck gewickelt sieht, führt er den Code aus und verwendet das Ergebnis.
lookup = function({t,u}, expr(a+b) );
New Table( "abc",
Add Rows( 2 ),
New Column( "a",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( eval( lookup(1,2) ) )
)
)
Die benutzerdefinierte "Lookup"-Funktion (Zeile 1) ist nicht sehr hell, aber sie muss ausgeführt werden, um expr(a+b) als Rückgabewert abzurufen. In Zeile 7 bedeutet der Wrapper eval(), dass die Spaltenformel nicht auf „lookup(1,2)“ gesetzt wird, sondern auf den Ausdruck, der von lookup(1,2) zurückgegeben wird.Dieselbe Tabelle wie zuvor, mit derselben Spaltenformel.
Was wäre, wenn Sie möchten, dass die Spaltenformel auf einen Ausdruck gesetzt wird, der mit eval( ) beginnt?Wie könnte der Formelbefehl das tun, da das Starten mit eval( ) bedeutet, das Argument auszuwerten und das Ergebnis zu verwenden? (Es wäre mir schwergefallen, ein interessantes Beispiel zu finden, aber FRAU hat einen in der Antwort auf die Frage.) Die Antwort ist Name Expr( ). Name Expr ist eine JSL-Funktion, die normalerweise verwendet wird, um einen Ausdruck aus einer JSL-Variablen zu erhalten, ohne ihn auszuwerten. Als äußerster Wrapper in einem Formelbefehl gibt er nur das Argument zurück, ohne es auszuwerten. Das erste Beispiel könnte es ohne guten Grund außer dieser Erklärung wie folgt verwenden, um genau dieselbe Tabelle zurückzugeben:
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( Name Expr( :a + :p</img> ) )
)
)
Aber für FRAU Beispielsweise wird es wegen der cleveren Verwendung von eval benötigt (was wahrscheinlich in einem anderen Blogbeitrag erklärt werden soll, was es tut). Hier ist die letzte Tabelle aus der ursprünglichen Frage. Ich habe meine eigene Idee als zweite Formelspalte hinzugefügt.
New Table( "final?",Add Rows( 9 ),
New Column( "color",Character,"Nominal",
Set Values({"green", "green", "blue", "yellow", "red", "red", "yellow", "green", "green"})),
New Column( "count",Numeric,"Continuous",Format( "Best", 12 ),
Formula( Name Expr( Eval( Eval Expr( Col Sum( Row() <= Expr( Row() ), :color ) ) ) ) )),
New Column( "another count",Numeric,"Continuous",Format( "Best", 12 ),
Formula(
n = 0;
For( i = 1, i <= Row(), i++,
If( :color == :color[i], n++ )
);
n;
)
)
);
Die Formel der dritten Spalte könnte auf Kosten der Übersichtlichkeit schneller sein, indem sie rückwärts nach der letzten Übereinstimmung sucht und diese Zahl um eins erhöht. Klarheit vs. Effizienz ist ein Kompromiss.

Also mache ich mich auf den Weg, um den Fehler zu beheben, der in diesem Prozess entdeckt wurde: Wenn eine Datentabelle ein Skript erstellt, um sich selbst zu reproduzieren (wie im oberen Beispiel), muss sie JSL erzeugen, um auch die Spaltenformeln zu reproduzieren. Wenn die Spaltenformel mit dem speziellen Wrapper eval( ) beginnt und eval Teil der Formel sein soll, muss JMP den Namensausdruck hinzufügen.
Update 21. April 2018: Reparatur der automatischen Konvertierung aus dem vorherigen Blog.