Inkonsistente akzeptable SyntaxAllCols = dt << Get Column Names();
AllColNames = dt << Get Column Names(string);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));
nnm2 = Col Number(newcol);
if(nnm2 == nnm1,
newcol << delete formula();
dt << Delete Columns(colcol);
newcol << set name(cname), //else
dt << Delete Columns(newcol);
);
);Ich verwende JMP18 unter Windows. Wenn ich Code schreibe, den ich häufig verwenden möchte, erstelle ich gerne eine Symbolleistenschaltfläche dafür. Manchmal stelle ich jedoch fest, dass Code, der aus einem geöffneten Skriptfenster ausgeführt werden kann, nicht aus einem Symbolleistensymbol ausgeführt werden kann. Hier ist ein Beispiel, in dem ich Spalten durchlaufe und sie von Zeichen in Zahlen ändere, wenn alle Einträge numerisch sind. Beim Ausführen aus einer Symbolleiste betrifft der Einwand die Zeile:
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));
Diese Syntax ist akzeptabel, wenn ich sie aus einem Skriptfenster ausführe!
Warum sollte der JSL-Interpreter in jeder Situation anders sein?
Welche Syntax hierfür wäre allgemein akzeptabel?
Bei sehr großen Datensätzen und Spalten kann dies langsam sein. Gibt es eine bessere Möglichkeit, dies zu tun?
Automatisierung und SkriptingDatenzusammenführung und -bereinigungWindowsBetreff: Inkonsistente akzeptable SyntaxWelche Fehlermeldung haben Sie erhalten? Ich denke, das Skriptfenster hat eine aktuelle Datentabelle, das Symbolleistenskript jedoch möglicherweise nicht. Vielleicht reicht es aus,
currentDatatable(dt);
am Anfang des Skripts würde ausreichen.
Sie könnten
print(currentDatatable());
zu Beginn des Skripts, um herauszufinden, was das Toolbar-Skript weiß.
Betreff: Inkonsistente akzeptable SyntaxSymbolleisten fügen Ihrem Skript möglicherweise Names Default To Here(1) hinzu (was meiner Meinung nach immer der Fall sein sollte).

Dies kann dann möglicherweise Fehler anzeigen, die nicht sichtbar wären, wenn sich alles im globalen Bereich befände (aber normalerweise sind es trotzdem Fehler). Ich erstelle meine Formeln entweder mit Eval(EvalExpr()) oder Eval(Substitute()).
Eval(EvalExpr(
newcol = dt << New Column("Temp", numeric, formula(Num(Expr(NameExpr(AsColumn(dt, i))))));
));
Bei großen Datensätzen müssen Sie für derartige Zwecke möglicherweise die Stichprobennahme in Betracht ziehen. Es gibt auch Lösungen ohne Formeln, die möglicherweise schneller sind, aber dies hängt möglicherweise auch von Ihren Daten ab.
Aus irgendeinem Grund habe ich dies nicht in der JMP-Community veröffentlicht (oder zumindest konnte ich es nicht finden), Zeichenspalten in Zahlen (github.com) . Sie können sich den Code ansehen, um zu sehen, wie ich diese Aufgabe ausgeführt habe, unter https://github.com/jthi-jmp-tools/character-columns-to-numeric/blob/main/bin/bin/character_columns_to_numeric.jsl . Ich habe dieses Skript inzwischen überarbeitet und wenn ich mich recht erinnere, verwende ich heutzutage eine etwas andere Methode.
Betreff: Inkonsistente akzeptable SyntaxSymbolleistensymbole kennen die aktuelle Datentabelle():
Das Problem ist eher das umgekehrte.
Bitte definieren Sie "dt=current data table()" vor dem
dt << Get Column Names();
Betreff: Inkonsistente akzeptable SyntaxDanke, Craig.
Die Fehlermeldung lautet:
Name nicht aufgelöst: 2PCS_X(um) in Zeile 1 beim Zugriff oder bei der Auswertung von '2PCS_X(um)' , "2PCS_X(um)"n /*###*/
„2PCS_X(um)“ ist der Name der ersten auszuwertenden Spalte.
Der Ausdruck für die erste Spalte sollte also lauten:
newcol = dtTOSA << neue Spalte("Temp", numerisch, Formel(Num( :"2PCS_X(um)"n )));
Betreff: Inkonsistente akzeptable SyntaxAußerdem verwende ich im eigentlichen Skript dt nicht als Variable. Ich verwende eine viel aussagekräftigere Variable, wie dtTOSA. (siehe oben) Immer wenn ich eine bestimmte Datentabelle ansprechen möchte, gebe ich dies explizit an, um Verwirrung zu vermeiden, wie ich es in dieser Anweisung getan habe. Ich verstehe nicht, wie der Interpreter denken könnte, ich beziehe mich auf eine andere Tabelle.
Betreff: Inkonsistente akzeptable SyntaxVielleicht, aber die Fehlermeldung deutet darauf hin, dass JMP nicht an der richtigen Stelle nach „2PCS_X(um)“n sucht. Ich bin nicht sicher, welchen Kontext das Symbolleistenskript verwenden kann.
Betreff: Inkonsistente akzeptable SyntaxCraig,
Ich habe Ihren Vorschlag befolgt und eine Druckanweisung verwendet und dabei festgestellt, dass ich nie zu der Zeile gelangt bin, die meiner Meinung nach das Problem darstellt.
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));Das Problem lag an dieser Zeile.
nnm1 = Col Number(colcol);
Also habe ich es folgendermaßen geändert und das hat funktioniert.
nnm1 = dtTOSA << Col Number(colcol);
Ich musste JMP später im Code auch noch einmal daran erinnern, was die aktuelle Tabelle war, und ich musste {} in „Spalten löschen“ verwenden, bevor es funktionierte. Aus irgendeinem Grund ist es JMP egal, ob diese geschweiften Klammern vorhanden sind, wenn es aus einem Skriptfenster ausgeführt wird.
Der Codeausschnitt ist nun dieser. Dies ist übrigens ein Ausschnitt aus einem längeren Code, der auch diese und eine weitere Tabelle erstellt.
AllCols = dtTOSA << Get Column Names();
AllColNames = dtTOSA << Get Column Names(string);
currentDatatable(dtTOSA);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = dtTOSA << Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dtTOSA << new column("Temp", numeric, set formula(eval(evalexpr(Fexpr))));
nnm2 = dtTOSA << Col Number(newcol);
if(nnm2 == nnm1,
currentDatatable(dtTOSA);
newcol << delete formula();
dtTOSA << Delete Columns({colcol});
wait(0);
newcol << set name(cname), //else
dtTOSA << Delete Columns({newcol});
);
);Jetzt gibt es jedoch ein anderes Problem. Obwohl ich die alte Spalte lösche, bevor ich die neue Spalte umbenenne, fügt JMP eine unerwünschte 2 nach dem Spaltennamen ein! Auch dies geschieht nicht, wenn es aus einem Skriptfenster ausgeführt wird. Ich habe versucht, eine wait(0)-Anweisung einzufügen, aber das hat nicht geholfen.
Wie kann das behoben werden?
Betreff: Inkonsistente akzeptable SyntaxTatsächlich wird der Vorgang zum Löschen der Spalte nicht ausgeführt.
dtTOSA << Delete Columns({colcol});Es bleiben also die ursprüngliche Zeichenspalte und die neue numerische Spalte erhalten.
Betreff: Inkonsistente akzeptable SyntaxSeltsamerweise funktioniert die Löschanweisung einwandfrei, wenn die Bedingung „else“ erfüllt ist.
Betreff: Inkonsistente akzeptable SyntaxObwohl auf die Spalte auf zwei verschiedene Arten verwiesen wird (einmal als Textzeichenfolgenname, einmal als Spaltentyp), hat es schließlich funktioniert. Ich schreibe seit 18 Jahren Code in JSL und finde es immer noch inkonsistent und verwirrend, Spalten in JSL als Variablen zu referenzieren.
AllCols = dtTOSA << Get Column Names();
AllColNames = dtTOSA << Get Column Names(string);
currentDatatable(dtTOSA);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = dtTOSA << Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dtTOSA << new column("Temp", numeric, set formula(eval(evalexpr(Fexpr))));
nnm2 = dtTOSA << Col Number(newcol);
if(nnm2 == nnm1,
currentDatatable(dtTOSA);
newcol << delete formula();
dtTOSA << Delete Columns(eval(cname));
currentDatatable(dtTOSA);
newcol << set name(cname), //else
dtTOSA << Delete Columns({newcol});
);
);Betreff: Inkonsistente akzeptable SyntaxIch verwende immer Zeichenfolgen als Spaltenbasis und baue dann meine Referenzen nach Bedarf daraus auf. Ich habe festgestellt, dass dies die flexibelste Möglichkeit ist, mit verschiedenen Arten von Referenzen umzugehen.
Wenn ich beispielsweise Ihr Skript nehme und einige Annahmen zu seinem Zweck treffe (beginnend mit der dritten Spalte, alle durchgehen, eine neue Formelspalte erstellen, in der Sie Werte in numerische Werte ändern, fehlende Werte vergleichen und Aktionen basierend auf dem Ergebnis ausführen), würde ich es in JMP18 folgendermaßen schreiben:
Names Default To Here(1);
dtTOSA = New Table("Untitled",
Add Rows(4),
Compress File When Saved(1),
New Column("Column 1",
Numeric,
"Continuous",
Format("Best", 12),
Set Values([1, 2, 3, 4])
),
New Column("Column 2", Character, "Nominal", Set Values({"A", "1", "2", "3"})),
New Column("Column 3", Character, "Nominal", Set Values({"1", "2", "3", "4"})),
New Column("Column 4", Character, "Nominal", Set Values({"A", "B", "C", "D"}))
);
wait(1); // demo purposes
cols = dtTOSA << Get Column Names("String");
// Remove From(cols, 1, 2); // skipping this for demo purposes
For Each({colname}, cols,
// colname = cols[3]; // for testing
Eval(EvalExpr(
newcol = dtTOSA << New Column("Temp", numeric, Formula(
Num(Expr(Name Expr(As Column(dtTOSA, colname))))
));
));
newcol << Run Formulas;
newcol << delete formula();
orig_vals = Col Number(Column(dtTOSA, colname));
new_vals = Col Number(Column(dtTOSA, (newcol << get name)));
If(orig_vals == new_vals,
dtTOSA << Delete Columns(colname);
newcol << set name(colname);
,
dtTOSA << Delete Columns(newcol)
);
);
Und wenn ich das von Anfang an machen würde, aber dennoch eine ähnliche Idee wie Sie verwenden würde, würde ich (zumindest in diesem Moment) so etwas machen
Names Default To Here(1);
dt = New Table("Untitled",
Add Rows(4),
Compress File When Saved(1),
New Column("Column 1",
Numeric,
"Continuous",
Format("Best", 12),
Set Values([1, 2, 3, 4])
),
New Column("Column 2", Character, "Nominal", Set Values({"A", "1", "2", "3"})),
New Column("Column 3", Character, "Nominal", Set Values({"1", "2", "3", "4"})),
New Column("Column 4", Character, "Nominal", Set Values({"A", "B", "C", "D"}))
);
wait(1); // demo purposes
cols = dt << Get Column Names("Character", "String"); // We only need to check character columns
For Each({colname}, cols,
dt_summary = dt << Summary(
Group(Eval(colname)),
Freq("None"),
Weight("None"),
Link to original data table(0),
output table name("Summar of " || colname),
Private
);
orig_vals = Col Number(Column(dt_summary, 1));
Column(dt_summary, 1) << Set Data Type("Numeric");
new_vals = Col Number(Column(dt_summary, 1));
Close(dt_summary, no save);
If(orig_vals == new_vals, // we can change
Column(dt, colname) << Set Data Type("Numeric");
Column(dt, colname) << Set Modeling Type("Continuous");
);
);
Ich neige dazu, dies mithilfe von Transform Each und Num zu tun, aber manchmal reicht es vielleicht auch, wenn Sie die Konvertierungen JMP überlassen (es gibt jedoch Fälle, in denen Sie dies vielleicht nicht tun möchten..., siehe Num() vom Skriptindex und wie es sich beispielsweise mit Num("5%") verhält. << Restrict vermeidet dieses Verhalten).
Betreff: Inkonsistente akzeptable SyntaxJarmo,
Danke für die Gedanken. Ich habe manchmal Tausende von Spalten und Zehntausende von Zeilen, und die Geschwindigkeit kann ein Problem sein. So wie ich es jetzt mache, konnte ich die Zeit tatsächlich auf etwa ein Drittel der Zeit reduzieren, die ich vorher gebraucht habe, aber das kann immer noch viele Minuten dauern. Ich könnte irgendwann einmal mit Ihrer Methode experimentieren, aber ich frage mich, ob Sie meinen, dass es langsamer oder schneller wäre, jedes Mal eine Übersichtstabelle zu erstellen.
Was den Umgang mit Spaltenreferenzen betrifft, habe ich versucht, Column(dt, colname) zu verwenden, aber das funktioniert nicht immer. In Ihrem Skript verwenden Sie jedoch auch As Column(). Wird As Column() in der Regel für Formeln verwendet?
Betreff: Inkonsistente akzeptable Syntax
@pcarroll1 schrieb:
Wird für Formeln grundsätzlich As Column() verwendet?
ja, entweder als column(columnname) oder :column(dt, columnname)[]
Betreff: Inkonsistente akzeptable SyntaxZur ersten „Frage“: Wenn Sie versuchen, die Geschwindigkeit für bestimmte Anwendungsfälle zu optimieren, müssen Sie einfach ausprobieren, was am besten funktioniert, da es viele verschiedene Methoden gibt und die schnellste möglicherweise stark von Ihren Daten abhängt. In diesem Fall habe ich eine Übersichtstabelle (oder Summarize) verwendet, um die Überprüfung auf Replikationswerte zu vermeiden, aber wie bereits erwähnt, hängt dies von Ihren Daten, Ihren JMP-Versionen und möglicherweise von anderen Dingen ab …
Für Spaltenreferenzen gilt meine Regel: Verwenden Sie immer den Spaltennamen und die Tabellenreferenz als Ausgangspunkt und erstellen Sie die endgültige Referenz daraus . Was ich als Referenz betrachte, hängt davon ab , wo und wie ich sie verwende. Wenn ich beispielsweise eine Formel erstelle, möchte ich, dass meine Formel Spalten als :mycol referenziert (und nicht AsColumn(mycol) oder Column(mycol)[], die normalerweise auch in Ordnung sind). Und ich kann das :mycol-Format mit dem ziemlich langen Stil von NameExpr(AsColumn(dt,colname)) mit Ausdrucksauswertung erhalten. Im Allgemeinen ist AsColumn(dt, colname) (ODER dt:colname) dasselbe wie Column(dt, colname)[Row()] (oder Column(dt, colname)[]), das den Wert der aktuellen Zeile erhält (meiner Meinung nach ist das nicht immer so. Auf Plattformen betrachte ich beispielsweise :mycol als Referenz und nicht als einen bestimmten Wert in einer Zeile...).
Dies gibt beispielsweise einen fehlenden Wert zurück, da mycol sofort ausgewertet wird und der anfängliche Row()-Wert in JMP 0 ist (kein Problem innerhalb einer Formel, da Row() ständig aktualisiert wird).
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
colname = "age";
mycol = NameExpr(AsColumn(dt,colname));
show(mycol)
Dies ist der am schwierigsten zu verstehende Unterschied bei Spaltenreferenzen, As Column() (Wert der aktuellen Zeile) vs Column() (Referenz auf eine Spalte) in JMP. Es ist sehr schwierig, zu verstehen, wie diese funktionieren... Ich habe es im Grunde durch viele, viele Fehlschläge gelernt. Und jetzt habe ich eine gute Vorstellung davon, was ich beim Erstellen eines Ausdrucks zuerst verwenden sollte (ich kann mich immer noch von Zeit zu Zeit irren). Zu diesem Thema möchte ich irgendwann einen Blogbeitrag schreiben, da meine Meinungen (derzeit) von denen anderer abweichen können und ich mich für einen ziemlich guten JMP-Skripter halte, ohne ein JMP-Entwickler (JSL) zu sein.
Eine Anmerkung hier : Ich bin kein JMP-Entwickler und es ist mir auch egal, wie Entwickler denken, dass JSL funktioniert (ich bin von Zeit zu Zeit anderer Meinung als Entwickler). Alle meine Antworten basieren immer auf meinen Erfahrungen mit den JMP-Versionen, die ich verwendet habe.
Es tut mir sehr leid, wenn dieser Beitrag etwas verwirrend ist (ich habe heute Abend vielleicht ein paar Bier getrunken:) ). Wenn Sie weitere Erläuterungen zu meinen Ansichten zu diesen Themen wünschen, können Sie in diesem Beitrag posten (markieren Sie mich aber mit @, damit ich es leichter erkennen kann). Sie können mir bei Bedarf auch eine private Nachricht senden.