SkriptHallo an alle,
Ich habe eine Datenbank, in der ich aus einer Formel oder einem Skript eine neue Spalte erstellen möchte.
Hier ein Überblick über die Datenbank:

- Spalte T stellt die auszuführenden Operationen dar
- Spalte X_3 stellt ein Feature dar
- Die op-Spalte stellt Objekte dar
Das Ziel besteht darin, eine Spalte „Bewertung“ zu erstellen, in der wir „ko“ und die Zahl entsprechend „op“ hinzufügen, wenn die Summe der Mängel von Zeile zu Zeile für dasselbe „obj“ unterschiedlich ist (hier Wert gleich AT). ).
Letzte Besonderheit: Die Bilanzspalte muss für die Anzahl der Vorgänge „3061“ ausgefüllt werden.
Dies ist eine Übersicht über die Datenbank. Die Spalte obj ist „A“, aber in der Datenbank ändert diese Spalte ihren Wert.
Danke für deine Antworten !
Automatisierung und SkripterstellungBetreff: SkriptWarum wird Zeile 6 op. 180 nicht zur letzten Spalte hinzugefügt? 0 unterscheidet sich von 1.
(Sie sollten informativere Beitragstitel als nur ein Wort verwenden)
Betreff: SkriptWeil die Summe für Zeile 6 gleich 0 ist. Tatsächlich ist es eher so, dass wenn die Summe der Mängel vom Wert 0 abweicht, man den Wert „op“ in der Spalte „Balance“ angibt.
Betreff: SkriptMuss also überprüft werden, ob sich die Werte zwischen zwei Zeilen unterscheiden? Oder interessieren Sie sich nur für Zeilen, in denen :op ungleich 0 ist?
Betreff: SkriptIch denke, wir können nur an Zeilen interessiert sein, bei denen der Wert von :sum default von 0 abweicht. Denn wenn der Wert von: Standardsumme 0 ist, wird in der Bilanzspalte nichts angezeigt.
Betreff: SkriptDanke für Ihre Antwort !
Beim Vergleich der beiden Methoden scheint mir die zweite für meinen Fall die bessere zu sein.
Ich habe es an meine Datenbank angepasst, die Spalten haben in beiden Datenbanken das gleiche Format und ich erhalte diese Art von Fehlermeldung:

Betreff: SkriptDa die Fehlermeldung auf Französisch ist, kann ich sie nicht verstehen. Es könnte sein, dass der Fehler letztendlich darauf hinweist, dass Sie keine bilan3-Spalte haben. (Es heißt, dass es einen ungültigen Index gibt, aber das liegt daran, dass die bilan3-Spalte nicht vorhanden ist. Dies liegt daran, dass dt[input_loc, „bilan3“] [](1, 0) zurückgibt, wenn Sie die Spalte nicht haben und dann versuchen, einige Werte dafür festzulegen.
Betreff: SkriptDies liegt daran, dass die Variable „input_loc“ leer ist. Für die Zuweisung neuer Zellen in der Spalte „Bilanz3“ ist dies also nicht möglich.
Betreff: SkriptDer Wert „3061“ (Zeichen, nicht Zahl) wird in Spalte „T“ nicht gefunden. Auch die Prüfung, die ich implementiert habe, um leere input_loc zu behandeln, ist falsch. Sie sollten sie auf < 1 statt auf < 0 ändern.
Betreff: SkriptDieses Skript erledigt beides und funktioniert mit dem bereitgestellten Beispiel. Ich empfehle Ihnen dringend, zu verstehen, was es tut, und zu fragen, ob es einige Teile gibt, die Sie nicht verstehen.
Names Default To Here(1);
dt = Open("$DOWNLOADS/AAA.jmp");
dt << New Column("bilan2", Character, Nominal);
dt << New Column("bilan3", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
/* comparing rows */
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
values = dt[object_rows, "SOMME DEFAUT"];
values1 = Remove(values, 1);
values2 = Remove(values, N Items(values));
differences = [0] |/ values1 - values2;
ops = dt[object_rows[Loc(differences != 0)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) < 0,
continue();
,
dt[input_loc, "bilan2"] = Repeat({result_str}, N Items(input_loc));
);
);
/* zeros */
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
values = dt[object_rows, "SOMME DEFAUT"];
ops = dt[object_rows[Loc(values)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) < 1,
continue();
,
dt[input_loc, "bilan3"] = Repeat({result_str}, N Items(input_loc));
);
);

Bearbeiten: If-Anweisung geändert If(N Items(input_loc) ... von < 0 bis < 1
Betreff: SkriptIn der Datenbank sind die Werte der Spalte :T für denselben Objekttyp nicht unbedingt in aufsteigender Reihenfolge angeordnet. Dies ist eine weitere :OPE-Spalte, deren Elemente in aufsteigender Reihenfolge angeordnet sind. Die Spalten :T und :OPE sind eng miteinander verbunden und für jeden Objekttyp eindeutig.
Die :OPEs, die kleiner sind als die :OPE-Werte, die dem Wert 3061 entsprechen, sollten nicht in die Bilanzspalte eingetragen werden.
Wenn die Werte von :OPE größer sind als die Werte :OPE, die dem Wert 3061 entsprechen, wird die bereits in den ersten Nachrichten beschriebene Operation ausgeführt.
Sehen Sie sich den folgenden Comic als Beispiel an:

Danke für deine Antworten !!
Betreff: SkriptFügen Sie zusätzliche Prüfungen für :OPE-Werte hinzu. Wenn der :OPE-Wert für die Zeile niedriger ist als der :OPE-Wert für „3061“, ignorieren Sie ihn. Es kann etwas schwierig sein, bei unterschiedlichen Indizes und Zeilen den Überblick zu behalten, aber das Hinzufügen von Debug-Ausdrucken hilft dabei. Auch wenn es für ein Objekt mehr als eine „3061“ geben kann, wird die Berechnung komplizierter.
Betreff: SkriptJa, ich verstehe, was du meinst!
Ich stelle mir etwas vor, das so aussieht:
If( col = Loc(dt[Row(), :OPE] < Loc(dt[Row(), :T=="3061")),
continue();
,
script...
);
Andererseits ist es unmöglich, dass dasselbe Objekt zweimal die Nummer 3061 hat.
Betreff: SkriptEs funktioniert nicht. Wissen Sie, wie ich so ein Skript erstellen kann? @jthi (die letzten durchzuführenden Kontrollen)?
Nochmals vielen Dank für Ihre Hilfe!
Betreff: SkriptRufen Sie alle :OPE-Werte für unique_object ab und rufen Sie dann den :OPE-Wert für die Zeile 3061 ab. Überprüfen Sie anschließend aus der Liste aller :OPE-Werte die Indizes, die höher als der :OPE-Wert für 3061 sind (Loc() kann dies tun).
Betreff: SkriptJa, das habe ich mir gesagt, ich habe an so etwas gedacht, aber die Schwierigkeit bleibt bestehen, die Variablen a und b zu definieren.
dt = current data table();
b = // all values :OPE for unique_object
a = // values :OPE for 3061
test = Loc(dt[Row(), b]) > Loc(dt[Row(),a]);
If( test=0 ,
continue();
,
script...;
);
Betreff: SkriptÄhnliche Methode wie für die Wertevariable, die :SOMME DEFAUT-Werte für ein bestimmtes eindeutiges Objekt speichert
values = dt[object_rows, "SOMME DEFAUT"];
Fügen Sie Debug-Drucke hinzu und versuchen Sie, das Skript Zeile für Zeile auszuführen, indem Sie nur ein Objekt verwenden
Betreff: SkriptJa, danke. Ich habe einen Code wie diesen geschrieben, der es mir ermöglicht, über die Informationen zu verfügen, die ich benötige:
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects);
b = dt[object_rows, "OPE"];
show(b);
a = dt << Get Rows Where( :T == "3061");
valeurs_OPE = :OPE[a];
show(valeurs_OPE);
valeurs_OPE_3061_obj = dt[unique_objects, "valeurs_OPE"];
show(valeurs_OPE_3061_obj);
);Allerdings kann ich die OPE-Werte, die der Aufgabe 3061 entsprechen, nicht über: obj (Variable „valeurs_OPE_3061_obj“) abrufen.
Nur die Variable „valeurs_OPE“ sammelt alle OPE-Daten, die der Aufgabe 3061 entsprechen.
Betreff: SkriptEs ist einfacher zu testen, wenn Sie For Each (vorerst) einfach ignorieren. Beginnen Sie mit so etwas
Names Default To Here(1);
// dt = Open("$DOWNLOADS/AAA.jmp");
// dt = Current Data Table();
dt = New Table("AAA(1)",
Add Rows(12),
Compress File When Saved(1),
New Column("obj", Character(16), "Nominal", Set Values({"A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "C", "C"})),
New Column("T", Character(4), "Ordinal", Set Values({"3052", "3061", "3082", "3940", "4012", "5010", "2890", "4060", "3061", "3081", "5010", "3061"})),
New Column("OPE", Numeric, "Continuous", Format("Best", 12), Set Values([12, 20, 32, 44, 56, 125, 210, 54, 60, 80, 45, 50])),
New Column("X__3", Character(4), "Nominal", Set Values({"rien", "rien", "incl", "ret", "ret", "rien", "incl", "incl", "ret", "incl", "ret", "rien"})),
New Column("SOMME DEFAUT", Numeric, "Continuous", Format("Best", 12), Set Values([0, 0, 1, 2, 1, 0, 2, 1, 2, 1, 1, 0])),
New Column("op", Character(12), "Nominal", Set Values({"40", "32", "55", "212", "510", "180", "2100", "2240", "2100", "500", "", ""})),
New Column("correct", Character, "Nominal", Set Values({"", "ko - 55 / ko - 212 / ko - 510 / ko - 2100", "", "", "", "", "", "", "ko - 500", "", "", "."}))
);
dt << New Column("bilan", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
unique_object = unique_objects[2];
object_rows = Loc(m_obs, unique_object);
input_loc = Loc(dt[object_rows, "T"], "3061"); // location of 3061 for unique_object
show(input_loc); // index within object_rows
show(object_rows[input_loc]); // real row number
opes = dt[object_rows, "OPE"]; // all OPE values for unique_object
valid_ope_idx = Loc(...//Betreff: Skript
Ich fuhr mit dem folgenden Skript fort:
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
show(value_OPE_3061);
//valid_ope_idx = Loc(b > value_OPE_3061);<BR /> //show(valid_ope_idx);
For( i = 1, i <= N Items(b), i++,
If(N Items(input_loc) < 1 & b[i] <= value_OPE_3061,
continue();
,
values = dt[object_rows, "SOMME DEFAUT"];
ops = dt[object_rows[Loc(values)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);
);Zuerst habe ich die Funktion Loc() verwendet, um die Zeilenindizes zu ermitteln, aber dann weiß ich nicht, wie ich mit dem Skript fortfahren soll. Also habe ich es mit einer „For“-Schleife versucht und das Ergebnis ist immer noch nicht korrekt. Können Sie mir helfen, voranzukommen?
Vielen Dank im Voraus für alle Antworten!
Betreff: SkriptEs macht keinen Sinn, „For Each Row“ wieder hinzuzufügen, bis andere Teile des Skripts funktionieren. Sie können mit dem von mir bereitgestellten Beispiel fortfahren, bis Sie den richtigen Wert für Zeile 9 festgelegt haben (aufgrund der Arbeit mit unique_objects[2], also
. Um OPE-Indizes zu erhalten, die höher als die „3061“ Zeilen-OPE sind, können Sie Loc wie folgt verwenden.
valid_ope_idx = Loc(opes > opes[input_loc]);
Beachten Sie, dass es sich hierbei um Indizes innerhalb der Operationsmatrix handelt, NICHT um Zeilen aus der Datentabelle. Um sie in Zeilen umzuwandeln, können Sie diese Indizes mit object_rows verwenden, da object_rows eine Matrix mit Zeilen für das spezifische eindeutige Objekt ist
Betreff: SkriptJa, ich stimme dir zu !
Die Werte, die ich mit meiner Formel finde, stimmen und ich finde die gleichen wie du.
Allerdings habe ich bei der Konstruktion der Fortsetzung des Drehbuchs größere Schwierigkeiten!
Weil ich die Werte „ko-.....“ zurückgeben muss /ko-...» wenn :OPE größer als :OPE ist, was :T = 3061 entspricht, und wenn :DEFAULT SUM von 0 verschieden ist (wie im Beispiel).
Betreff: SkriptSie fahren mit einer ähnlichen Idee fort
- Überprüfen Sie, ob in valid_ope_idx mehr als 0 Elemente vorhanden sind
- Rufen Sie alle Werte für valid_ope_idx ab
- Ermitteln Sie daraus dann die Indizes der Werte, die größer als 0 sind
- Und dann können Sie damit endlich die Werte von :op für diese spezifischen Indizes erhalten (denken Sie daran, sie zuerst in Zeilen umzuwandeln).
- Verketten Sie diese Werte mit Concat Items()
- Wert zur richtigen Zeile hinzufügen
Betreff: SkriptIn meiner Testdatenbank funktioniert es mit dem folgenden Code einwandfrei:
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
Starts With( col_name, "SOMME" )
);
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
show(value_OPE_3061);
valid_ope_idx = Loc(b > value_OPE_3061 & dt[object_rows,somme_col] > 0) ;
show(valid_ope_idx);
if( N items(valid_ope_idx) < 1,
continue();
,
ops = dt[object_rows[valid_ope_idx], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);Allerdings ist es in meiner endgültigen Datenbank möglich, dass für dasselbe obj mehrmals der Wert :T = 3061 angezeigt wird (andererseits sind die Werte von OPE gleich!).
Ich denke, dass noch etwas geändert werden muss, der Wert von value_OPE_3061 muss eindeutig sein (und nicht zum Beispiel value_OPE_3061 = [ 50 , 50 , 50 ], sondern value_OPE_3061 = [ 50 ]).
Gibt es in JMP eine Funktion zum Entfernen von Duplikaten aus einem Array/einer Liste?
Danke für deine Antworten !
Betreff: SkriptIch dachte vorhin, Sie sagten, es sei unmöglich, dass es mehrere „3061“-Werte gäbe?
Eine Möglichkeit zum Entfernen von Duplikaten besteht darin, Associative Array() mit << get-Schlüsseln zu verwenden (funktioniert nicht, wenn Sie Floats haben). Eine andere gute Möglichkeit wäre in diesem Fall die Verwendung von Design(<
Betreff: SkriptIch habe diesen Teil hinzugefügt, er funktioniert noch besser:
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
Starts With( col_name, "SOMME" )
);
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
if( N items(input_loc) < 1,
continue();
,
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
liste={}; // transformer en liste pour supprimer les doublons
for (i = 1, i <= NRows(value_OPE_3061), i++,
for (j = 1, j <= NCols(value_OPE_3061), j++,
InsertInto(liste, value_OPE_3061[i, j]);
);
);
// supprimer les doublons
if( N items(liste) <= 1,
a = liste;
,
a = Left(liste,1);
);
// repasser en matrice pour faire les comparaisons
Mat_3061 = Matrix(a);
show(Mat_3061);
valid_ope_idx = Loc(b > Mat_3061 & dt[object_rows,somme_col] > 0) ;
show(valid_ope_idx);
if( N items(valid_ope_idx) < 1,
continue();
,
ops = dt[object_rows[valid_ope_idx], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);
);Eigentlich hast du recht @jthi , aber ich habe gesagt, dass es für einen Wert 3061 eines :obj keine unterschiedlichen Werte der Variablen :OPE geben kann (danach kann es in einem obj beispielsweise zweimal den Wert :T gleich 3061 geben, aber der Wert :OPE wird derselbe sein).
Am Ende möchte ich in der Ausgabe, dass sich die Anzeige nicht wiederholt, wenn für dasselbe :obj mehrere Male der Wert :T gleich 3061 vorhanden ist.
Beispiel :

Mit einem Skript wie diesem:
input_loc = Loc(dt[object_rows, "T"], "3061");// localiser 3061 pour chaque objet
liste2={}; // transformer en liste pour supprimer les doublons
for (i = 1, i <= NRows(input_loc), i++,
for (j = 1, j <= NCols(input_loc), j++,
InsertInto(liste2, input_loc[i, j]);
);
);
// supprimer les doublons
if( N items(liste2) <= 1,
c = liste2;
,
c = Left(liste2,1);
);
// repasser en matrice pour faire les comparaisons
loc_3061 = Matrix(c);
Es funktioniert korrekt, ich nehme den ersten Index, der :T entspricht, gleich 3061.
Aber wie in der Aufnahme oben möchte ich die doppelten Elemente in derselben Zeile entfernen können:
kb - 2203 / kb - 2203 --> kb - 2203
Betreff: SkriptSie könnten einfach den ersten Index auswählen, der den Wert 3061 für das Objekt hat.
Betreff: SkriptIn etwa so hätte ich das gelöst. Sollte mit den Beispieldaten funktionieren
Names Default To Here(1);
// dt = Open("$DOWNLOADS/AAA.jmp");
// dt = Current Data Table();
dt = New Table("AAA(1)",
Add Rows(12),
Compress File When Saved(1),
New Column("obj", Character(16), "Nominal", Set Values({"A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "C", "C"})),
New Column("T", Character(4), "Ordinal", Set Values({"3052", "3061", "3082", "3940", "4012", "5010", "2890", "4060", "3061", "3061", "3081", "5010", "3061"})),
New Column("OPE", Numeric, "Continuous", Format("Best", 12), Set Values([12, 20, 32, 44, 56, 125, 210, 54, 60, 60, 80, 45, 50])),
New Column("X__3", Character(4), "Nominal", Set Values({"rien", "rien", "incl", "ret", "ret", "rien", "incl", "incl", "ret", "ret", "incl", "ret", "rien"})),
New Column("SOMME DEFAUT", Numeric, "Continuous", Format("Best", 12), Set Values([0, 0, 1, 2, 1, 0, 2, 1, 2, 2, 1, 1, 0])),
New Column("op", Character(12), "Nominal", Set Values({"40", "32", "55", "212", "510", "180", "2100", "2240", "2100", "2100", "500", "", ""}))
);
dt << New Column("bilan", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) == 0,
continue();
//Throw("3061 not found");
, N Items(input_loc) > 0,
input_loc = input_loc[1];
);
opes = dt[object_rows, "OPE"];
valid_ope_idx = Loc(opes > opes[input_loc]);
If(N Items(valid_ope_idx) < 1,
result_str = ".";
,
values = dt[object_rows[valid_ope_idx], "SOMME DEFAUT"];
ops = dt[object_rows[valid_ope_idx[Loc(values)]], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
);
dt[object_rows[input_loc], "bilan"] = result_str;
);