Wie man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten erstelltIch möchte eine Spaltenliste anhand bestimmter Auswahlkriterien erstellen. Die Spaltennamen sind dabei nicht im Voraus bekannt. Anschließend möchte ich mithilfe dieser Spaltenliste eine Formelspalte erstellen, die den Mittelwert (oder die Standardabweichung oder die Anzahl) dieser Spalten berechnet.
Einfaches Beispielskript, das alle numerischen Spalten verarbeitet:
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
ColList = {};
For(i=1, i<=NCols(), i++,
If(Column(i)<
<GETDATATYPE></GETDATATYPE>
<BR /> <BR /> <P>Beachten Sie, dass ColList eine gültige Spaltenliste ist. Wenn diese in die Formel der ersten Spalte eingefügt wird, zeigt die Vorschau im Formeleditor zwar die korrekte Auswertung an, die Spalte bleibt jedoch leer. Offenbar müssen wir Skalare, Listen oder Matrizen in die Funktion Mean() einfügen (die Vorschau funktioniert aber unabhängig davon).</P> <P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><span class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><img src="https://us.v-cdn.net/6038925/uploads/images/115064i3C11FFA7C1D866DE/pauldeen_0-1788272598908.png" role="button" title="pauldeen_0-1788272598908.png" alt="pauldeen_0-1788272598908.png" /></span><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN></P> <P>Die zweite Formelspalte fügt eine AsColumn()-Funktion um die Spaltenreferenz hinzu… was etwas kontraintuitiv ist, da es sich ja bereits um eine Spalte handelt. Dadurch wird jedoch eine Liste, ein Skalar oder eine Matrix erstellt, und die Mittelwert()-Formel funktioniert.</P> <P>Ich habe das Gefühl, ich mache es mir unnötig kompliziert. Gibt es eine einfachere Möglichkeit, eine solche Zusammenfassungsspalte prozedural zu generieren?</P>
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?In einfachen Fällen wie diesem verwende ich normalerweise die Funktion „Ersetzen“, um die Liste durch einen anderen Ausdruck zu ersetzen.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Cars.jmp");
collist = dt << Get Column Names("Numeric", "String");
colrefs = Transform Each({colname}, collist,
Name Expr(As Column(dt, colname))
);
mexpr = Substitute(colrefs, Expr(List), Expr(Mean));
Eval(EvalExpr(
dt << New Column("AVG", Numeric, Continuous, Formula(
Expr(Name Expr(mexpr))
));
));
Write();
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Danke, aber das ist immer noch eine sehr fortgeschrittene Lösung für ein einfaches Problem. Ich bin weiterhin gespannt, ob jemand eine einfachere Möglichkeit findet, Spaltenbezüge in eine Spaltenformel einzufügen.
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Angenommen, wir haben eine Spalte namens „TEST“ in der Tabelle dt. Es gibt Unterschiede zwischen dem „Basis“-Test und dem „Basis“-Test.
- Column(dt, "TEST")
- AsColumn(dt, "TEST")
- "PRÜFEN"
- Name Expr(As Column(dt, "TEST"))
Mehr anzeigen...
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Cars.jmp");
Row() = 0; // default row value
col = "Size";
Show(col);
Show(Column(dt, col));
Show(AsColumn(dt, col));
Show(Name Expr(AsColumn(dt, col)));
Show(dt:col);
Show(AsName(col));
Write("\!N\!N");
Row() = 1;
Show(Column(dt, col)[Row()]);
Show(AsColumn(dt, col));
Show(Name Expr(AsColumn(dt, col)));
Show(dt:col);
Show(AsName(col));
Welche Art von Lösung suchen Sie? Spaltenbezüge werden Formeln nur dann hinzugefügt, wenn Sie eckige Klammern [] oder [Zeile()] verwenden. Wenn Ihre Spalten als Bezüge (oder Zeichenketten) vorliegen, müssen Sie diese in der Regel in Spaltenzugriffe umwandeln, um sie in Formeln verwenden zu können.
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Ich habe einen Fehlerbericht an JMP gesendet.
Der Fehler besteht darin, dass die Spaltenformel keine Argumente vom Typ `Column("Name")` akzeptiert, sondern diese zuerst in einen `As Column()`-Ausdruck eingeschlossen werden müssen. Im visuellen Formeleditor können Spalten in den Argumentfeldern abgelegt werden, daher sollte JSL dasselbe Verhalten widerspiegeln. Die Implementierung dieser Funktion in JSL würde die Erstellung von Spaltenformeln erheblich vereinfachen.
Offenbar interpretiert das Vorschaufenster im Formeleditor dies korrekt, da es eine Vorschau anzeigt.
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Column() und AsColumn()/:colname sind nicht dasselbe und sollten nicht auf ähnliche Weise verwendet werden.
Meiner Meinung nach liegt der Fehler hier im Formeleditor und dessen Darstellung von Formeln, die mit JSL erstellt wurden. Fehlerhafte Formeln (wie in diesem Fall) werden nicht erkannt, und Fehlermeldungen werden nicht angezeigt, wenn sie angezeigt werden sollten.
jthi_1-1788881236165.pngjthi_1-1788881236165.pngjthi_1-1788881236165.png
jthi_2-1788881243139.pngjthi_2-1788881243139.pngjthi_2-1788881243139.png
jthi_4-1788881274171.pngjthi_4-1788881274171.pngjthi_4-1788881274171.png
In diesem Fall sollte dies in den Spalteneigenschaften angezeigt werden.
jthi_7-1788882167381.pngjthi_7-1788882167381.pngjthi_7-1788882167381.png
und dies im Formeleditor
jthi_6-1788882151203.pngjthi_6-1788882151203.pngjthi_6-1788882151203.png
Und wenn Sie versuchen, es anzuwenden, tritt folgender Fehler auf:
jthi_5-1788882131736.pngjthi_5-1788882131736.pngjthi_5-1788882131736.png
Wenn Sie es auf Column()[] ändern, wird es korrekt angezeigt und liefert korrekte Ergebnisse.
jthi_0-1788880964367.pngjthi_0-1788880964367.pngjthi_0-1788880964367.png
Es liegt jedoch im Ermessen der JMP-Entwickler, wie sich dies ihrer Meinung nach verhalten sollte.
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Jarmo hat gute Argumente vorgebracht und eine alternative Lösung mit Column("name")[] vorgeschlagen. Wie Jarmo bereits erwähnte, sieht die Verwendung von Column("name")[] im Formeleditor nicht so übersichtlich aus. Meine unten stehende Lösung geht nicht auf diese Option ein, erklärt aber, warum dies für viele Benutzer verwirrend ist. Sie wiederholt zwar vieles von dem, was Jarmo bereits geschrieben hat, aber da ich es ohnehin schon getippt hatte…
Das vom OP gezeigte Skript ist kein Fehler, sondern das erwartete Verhalten. Es verdeutlicht ein Missverständnis, das viele Nutzer im Umgang mit Spaltenreferenzen und der Auswertung von Spaltenformeln haben.
Der Kern der Verwirrung liegt im Verständnis des Unterschieds zwischen der Syntax `Column("name")` und der Syntax `:name`. Beide sind unter bestimmten Umständen gültige Möglichkeiten, auf Spalten zu verweisen, liefern aber unterschiedliche Ergebnisse. Genauer gesagt: `Column("name")` gibt eine Referenz auf ein Spaltenobjekt zurück, während `:name` den Wert der Spalte „name“ in der aktuellen Zeile zurückgibt. Übrigens ist `:name` die Operatorform der Funktion `As Column("name")`. Anders ausgedrückt: Beide liefern im Prinzip dasselbe.
Das folgende Beispielskript veranschaulicht dies. Dieses Skript setzt voraus, dass die Datentabelle „Cars.jmp“ in Ihrer JMP-Sitzung geöffnet und aktuell ist.
Names Default To Here(1);
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
// sending messages to a column; either syntax works
Column(dt, "Year") << Set Property("Range Check", LELE(87, 97));
dt:Head IC << Set Property("Spec Limits", {LSL( 150 ), Show Limits( 1 )});
// Return values
// returns a column object reference shown as Column( "Year" ) in log
Column(dt, "Year"); // returns Column( "Year" )
// returns value in Year column on the current row.
// Since current row is 0 (the default invalid row number), returns missing (.)
:Year; // returns .
// Set the current row to the first row
Row() = 1;
:Year; // returns 87
Vor diesem Hintergrund ist klar, dass JMP den Mittelwert mehrerer Spaltenreferenzen nicht berechnen kann. Daher schlägt die erste Spaltenformel fehl. Die Funktion MITTELWERT() benötigt Werte, die in der zweiten Spaltenformel angegeben werden. Beim Auswerten der Spaltenformeln einer Datentabelle wird die aktuelle Zeile auf 1 gesetzt und anschließend der in der Formel-Eigenschaft gespeicherte Ausdruck ausgewertet. Der Rückgabewert wird in die Zelle der Spalte in der aktuellen Zeile eingetragen. Danach wird die aktuelle Zeile auf den nächsten Wert gesetzt und der Vorgang wiederholt. Diese Schritte werden so lange wiederholt, bis die Formel für die letzte Zeile ausgewertet ist. Folglich muss die Syntax der Spaltenformel so beschaffen sein, dass sie für jede Zeile der Datentabelle ausgewertet werden kann.
Für mich gibt es in Ihrem Beispielskript ein unerwartetes Ergebnis. Die Syntax `As Column(Column("name"))` wird nämlich genauso ausgewertet wie `As Column("name")`. Ich hatte erwartet, dass dies einen Fehler auslöst, aber JMP akzeptiert die Syntax und interpretiert sie korrekt. Das ist der (manchmal) Vorteil einer Skriptsprache gegenüber einer formalen Programmiersprache. Ich würde Ihnen jedoch nicht empfehlen, diese Syntax zu verwenden, da sie in Zukunft möglicherweise zu Fehlern führt.
Ich denke, der beste Weg, das Ziel mit dem Beispielskript zu erreichen, ist, die erste Methode mit einer Spaltenformel zu verwerfen und die zweite zu verwenden. Die zusätzliche Änderung besteht darin, ColList als Liste von Spaltennamen anstatt von Spaltenreferenzen zu definieren. Hier ist eine modifizierte Version des ursprünglichen Skriptbeispiels, die robust sein sollte.
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
ColList = {};
For( i = 1, i <= N Cols(), i++,
If( Column( i ) << GetDataType == "Numeric",
Insert Into( ColList, <FONT color="#FF6600"><STRONG>Column( i ) << Get Name</STRONG></FONT> )
)
);
MeanExpr2 = Name Expr( Mean() );
For( i = 1, i <= N Items( ColList ), i++,
Insert Into( MeanExpr2, Name Expr( As Column( ColList[i] ) ) )
);
Eval( Eval Expr( dt << New Column( "Average of numerics 2", Formula( Expr( Name Expr( MeanExpr2 ) ) ) ) ) );
Betreff: Wie erstellt man mit JSL eine Durchschnittsspalte basierend auf zufälligen Spalten?Aus theoretischer und funktionaler Sicht haben Sie wahrscheinlich völlig Recht … aber die Benutzeroberfläche verhält sich anders. Ich wähle Spalten aus der Tabelle aus und ziehe sie auf den `mean()`-Operator, woraufhin die Berechnung erfolgt. In Skripten kann ich jedoch keine Spalten auswählen, sondern muss String-Objekte (die den Spaltennamen entsprechen) auswählen und JSL anweisen, diese als Spaltenreferenzen zu interpretieren, die ich dann in den `mean()`-Operator einfügen kann. Wäre es nicht eine einfache Lösung, die JSL-Operatoren so zu erweitern, dass sie `Column("Name")` als Spaltenobjekte behandeln, die auf die Zeile indiziert werden können? Das wäre viel intuitiver und würde dem Verhalten der Benutzeroberfläche und damit dem Benutzerverständnis entsprechen. Wie Sie bereits erwähnt haben, herrscht diesbezüglich große Verwirrung bei den Benutzern.
Und zu Jarmos Anmerkungen: Die Fehlermeldungen im Formeleditor bedürfen einer Verbesserung hinsichtlich Klarheit und Konsistenz. Nochmals: Beachten Sie, dass die Vorschau die korrekte Auswertung anzeigt, die Formel jedoch bei Verwendung der Syntax „Spalte("Name")“ nicht ausgewertet wird.