„Zeilen abrufen wo“ dauert viel zu langeIch habe eine Referenztabelle, in der jede Spalte ein Name aus einer Spalte der Hauptdatentabelle ist und die Werte in den Zeilen die Teilenummern sind, die fehlerhafte Daten für diese Spalte in der Haupttabelle enthalten.So ist beispielsweise in der Haupttabelle Spalte 1 die Teilenummer und Spalte 2 „Temp“.Nehmen wir an, die Zeilennummer entspricht der Teilenummer, sodass Zeile 1 Teil „1“ ist und in der Spalte „Temp“ den Wert 65 hat.Teil 2 hat eine Temperatur von -100 und ist daher fehlerhaft.In der Referenztabelle unter der Spalte mit dem Namen „Temp“ ist der Wert von Zeile 1 also „2“.Dies wird für alle Teilenummern wiederholt, die fehlerhafte Daten in der Haupttabelle enthalten, und dann auch für jede Spalte.
Dadurch erhalte ich eine Referenztabelle mit fehlerhaften Daten, die ich dann durchlaufen kann, um die fehlerhaften Daten jedes Mal automatisch zu entfernen, wenn ich die neuesten Daten für die Haupttabelle abrufe.Ich habe den Code, der funktioniert, aber die Zeile:
(wobei vlist alle Teilenummern aus der Referenztabelle enthält und dt2 die Hauptdatentabelle ist)
try(rowindex=dt2 << Get Rows Where(contains(vlist,:WORKORDERNO )));
ist super langsam.Es dauert 22 Sekunden, bis der Vorgang abgeschlossen ist.Da ich 196 Spalten durchgehen muss, dauert das viel zu lange.Für Vorschläge zur Beschleunigung wären wir dankbar!
Der vollständige Code ist hier:
names default to here(1);
dt=open("J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp", invisible(1)); //this is the reference table
dt<<BEGIN data="https://community.jmp.com/" update=""></BEGIN>Automatisierung und SkripterstellungWindowsBetreff: „Zeilen abrufen wo“ dauert viel zu langeÜberlegen Sie, wie JMP die Namensauflösung durchführen wird.Wenn Sie a ausführen Zeilen abrufen Where() Mit dieser Funktion wird die Tabelle Zeile für Zeile durchsucht und ausgewertet Wo Ausdruck.Jede Auswertung erfordert eine Namensauflösung für alle definierten Variablen vlist Wenn vairable außerhalb der laufenden Schleife definiert wird, muss es bei jeder Iteration einige Scope-Walks durchführen, was zu einer Menge verschwendeter Arbeit führt.
Um dies zu umgehen, sollten Sie erwägen, alle Namen vorab auszuwerten, die während der Suche konstant bleiben, wie folgt:
Names Default To Here( 1 );
dt = Open(
"J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp",
invisible( 1 )
); //this is the reference table
dt << begin data update;
cols = dt << get column names();
dt2 = Data Table( "Master data pull daily download" ); //this is the main table
dt2 << begin data update;
dt2 << Clear Select();
cols2 = dt2 << get column names();
vlist = {};
For( i = 1, i <= 2 /*N items(cols)*/, i++,
Try( vlist = Column( dt, cols[i] ) << get values );
starttime = Tick Seconds();
Eval( Eval Expr(
Try( rowindex = dt2 << Get Rows Where( Contains( Expr( vlist ), :WORKORDERNO ) ) );
) );
endtime = Tick Seconds();
Print( "run time", Eval Insert( "Analysis took ^round(endtime - starttime)^ seconds" ) );
Try( Column( dt2, cols[i] )[rowindex] = . );
);
dt2 << end data update;
dt << end data update;
Close( dt, nosave );Beachten Sie die Eval( Eval Expr( ... Ausdruck( vlist ) ... ) ) Ausdruck – das ist eine Vorabbewertung vlist da es während der gesamten Schleife eine Konstante sein wird.
Betreff: „Zeilen abrufen wo“ dauert viel zu langeIch glaube, Sie können AsConstant(vList) verwenden, um den gleichen Effekt zu erzielen. Der Name „vlist“ sollte nur einmal für jeden GetRowsWhere-Aufruf ausgewertet werden.
Betreff: „Zeilen abrufen wo“ dauert viel zu langeDanke für die Antwort @ErraticAttack , ich habe Ihre Codeänderungen eingefügt und der Code wurde in 21 Sekunden gegenüber 22 Sekunden ausgeführt.Also etwas besser, aber nicht dort, wo ich sein muss.Alle weiteren Ideen wären willkommen!
Betreff: „Zeilen abrufen wo“ dauert viel zu langeIch finde auch, dass die Verwendung von Loc in den meisten Situationen wie dieser schneller ist, wenn Sie einen Weg finden, es zu verwenden. Möglicherweise gibt es einen besseren Weg als diesen, aber Sie können so etwas versuchen, um den GetRowsWhere-Aufruf zu ersetzen.
dt = New Table( "BadTable",
Add Rows( 100 ),
New Column( "BadPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
dt2 = New Table( "FullTable",
Add Rows( 10000 ),
New Column( "NewPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
newPNumbers = dt2:NewPartNumbers<< GetValues;
badPNumbers = AssociativeArray(dt:BadPartNumbers << GetValues);
rowIndex = Loc(Matrix(badPNumbers << GetValues(AsList(newPNumbers))));
Ich bin mir nicht ganz sicher, wie Ihre Tabellen aufgebaut sind, aber im Grunde werden dadurch die fehlerhaften Teilenummern in ein assoziatives Array umgewandelt, in dem fehlerhafte Teilenummern 1 und alles andere 0 zurückgeben. Wenn Sie eine Liste aller Teilenummern an GetValues übergeben, wird für jede Zeile eine Liste mit Einsen und Nullen zurückgegeben. Wenn Sie Loc dazu aufrufen, werden die Indizes zurückgegeben, bei denen 1 gefunden wird, was den Zeilen mit fehlerhaften Teilenummern entsprechen sollte.
Betreff: „Zeilen abrufen wo“ dauert viel zu lange@ErraticAttack Also habe ich eine Test-Stammdatentabelle und eine Referenztabelle erstellt, um zu versuchen, sie zu teilen, damit die Leute mitspielen können, aber als ich das tat, lief das Skript sehr schnell, in weniger als einer Sekunde.Jetzt frage ich mich, ob es etwas mit meiner tatsächlichen Datentabelle zu tun hat?
Hier sind die Testtabellen

Betreff: „Zeilen abrufen wo“ dauert viel zu langeAbhängig von Ihren Daten gibt es viele verschiedene Methoden, mit denen Sie diese Prüfungen durchführen können (Joins/Updates, Loc, Zeilen abrufen, wo, assoziatives Array, Übersichtstabelle ...). Wie viele Zeilen haben Ihre Tabellen? Wie viele verschiedene Werte gibt es maximal in den Spalten Ihrer Referenztabelle? Sind die meisten Werte leer (entfernen Sie leere Werte vor dem Vergleich, um die Liste zu verkleinern, oder fügen Sie sie dort nur einmal ein)?
Betreff: „Zeilen abrufen wo“ dauert viel zu langeHey @jthi ,
Hier ein Überblick über die Haupttabelle:

und hier ist die Ref-Tabelle:

Hier sehen Sie, wie viele Daten jede Spalte in der Referenztabelle enthält: (aus der Ausgabe des fehlenden Daten-Screeners)
Nummer fehlt
0
0
0
0
3115
6075
12237
16591
16591
16591
16591
16772
17038
17093
17095
17095
17099
17099
17109
17110
17113
21542
22781
23634
24792
24792
25058
25172
25280
25341
25356
25376
25376
25827
25863
25875
25893
25894
25897
25905
25942
25957
25963
25963
25963
25965
25968
25968
25968
25968
26367
26564
27190
27404
27414
27420
27437
27453
27465
27474
27478
27493
27503
27522
27547
27553
27573
27592
27597
27597
27597
27597
27619
27626
27628
27628
27629
27629
27629
27629
Aufgrund der wenigen Spalten, die eine Menge fehlerhafter Daten enthalten, sind die meisten Spalten voller „fehlender Daten“/Leerzeichen.
Ich frage mich, ob all diese Leerzeichen in der Vlist die Verlangsamung verursachen:

Betreff: „Zeilen abrufen wo“ dauert viel zu langeIch vermute, dass alle Leerzeichen dazu führen, dass Ihr Code langsamer wird.Hier ist eine Lösung dafür.Ersetzen Sie einfach Ihre Erstellung der Vlist durch
Try( vlist = Associative Array( As Column( cols[i] ) ) << get keys );
If( vlist[1] == "",
Remove From( vlist, 1, 1 )
);
Betreff: „Zeilen abrufen wo“ dauert viel zu langeHöchstwahrscheinlich führt dies zu einer Verlangsamung, insbesondere wenn der Wert nicht in der Liste gefunden wird
Names Default To Here(1);
test = {"a", "b", "c", "d", "e", "f"};
test2 = test || Repeat({""}, 27629);
lookup_val = "a";
repeats = 200;
tests = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests, (end-start)/1e6);
);
tests2 = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test2, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests2, (end-start)/1e6);
);
Show(Mean(tests), Std Dev(tests), Mean(tests2), Std Dev(tests2));
Show(Median(tests2)/Median(tests));
Bearbeiten:
Beide Testskripte sind relativ schnell geschrieben, sodass einige Fehler auftreten können
Names Default To Here(1);
Random Reset(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::10])),
New Column("second", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
Column(dt_lookup, "second") << Set Data Type("Character");
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "first"]), :first));
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "second"]), :second));
end = HP Time();
show((end - start)/1e6);
wait(0);
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "first"]) << get keys), :first));
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "second"]) << get keys), :second));
end = HP Time();
show((end - start) / 1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);
Abhängig davon, wie viele Werte Sie haben und ob es sich um Zeichen handelt (ich glaube, in Ihrem Fall sind das so), ist die Verwendung von Summarize() anstelle von Associative Array() schneller, um die eindeutigen Werte zu erhalten, aber das wird höchstwahrscheinlich nicht so groß sein eines Effekts in diesem Fall
Names Default To Here(1);
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("test", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "test") << Set Data Type("Character");
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(Column(dt_lookup, "test")));
end = HP Time();
show((end - start) / 1e6);
start = HP Time();
uniq_vals2 = Associative Array(Column(dt_lookup, "test")) << get keys;
end = HP Time();
show((end - start) / 1e6);
Show(N Items(uniq_vals), N Items(uniq_vals2));
Close(dt_lookup, no save);Betreff: „Zeilen abrufen wo“ dauert viel zu langeDies gehört höchstwahrscheinlich zur Kategorie der vorzeitigen Optimierung, aber die Aktualisierung von JMP kann manchmal sehr schnell sein und könnte hier höchstwahrscheinlich mit einigen Spaltenumbenennungen und dem Hinzufügen einer neuen Spalte zu Ihrer Nachschlagetabelle verwendet werden, die voller leerer Werte ist
Names Default To Here(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::30000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
/*
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(:first));
r = dt_data << Get Rows Where(Contains(As Constant(uniq_vals), :first));
dt_data[r, "second"] = "";
end = HP Time();
Show((end-start)/1e6);
*/
missing_col = dt_lookup << New Column("missing_vals", Numeric, Nominal);
start = HP Time();
i = 1;
Column(dt_lookup, "first") << Set Name(Char(i));
missing_col << Set Name("second");
dt_data << Update(With(dt_lookup), Match Columns(:first = Eval(Char(i))), Replace Columns in Main Table(:second));
end = HP Time();
Show((end-start)/1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);Betreff: „Zeilen abrufen wo“ dauert viel zu langeDas hat super funktioniert, danke!
Dank an @jthi sowie!Ich habe mich nicht intensiv mit seinem Code beschäftigt, den er oben gepostet hat, da das Kopieren und Einfügen des Txnelson-Codes perfekt funktioniert hat, aber ich weiß es zu schätzen, dass er sich die Zeit genommen hat, ihn zu erstellen.